KAOS/code/internal/supervisor/reporter_test.go
djuka 028872be43 T05: Reporter — pisanje izveštaja
- WriteReport generiše markdown izveštaj u reports/
- formatDuration, truncateOutput za formatiranje
- Kreira folder ako ne postoji, skraćuje output na 50 linija
- 10 reporter testova — svi prolaze
- T03 premešten u done/

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 11:48:05 +00:00

210 lines
4.9 KiB
Go

package supervisor
import (
"os"
"path/filepath"
"strings"
"testing"
"time"
)
func makeTestData(allPassed bool) (Task, RunResult, VerifyResult) {
task := Task{
ID: "T07",
Title: "Test feature",
Agent: "coder",
Model: "Sonnet",
Description: "Implement test feature.",
}
run := RunResult{
TaskID: "T07",
StartedAt: time.Date(2026, 2, 20, 10, 15, 0, 0, time.UTC),
FinishedAt: time.Date(2026, 2, 20, 10, 23, 45, 0, time.UTC),
Duration: 8*time.Minute + 45*time.Second,
ExitCode: 0,
Output: "Task completed successfully.\nAll tests passed.",
}
verify := VerifyResult{
Build: CheckResult{
Name: "build", Status: "pass",
Duration: 300 * time.Millisecond,
},
Vet: CheckResult{
Name: "vet", Status: "pass",
Duration: 200 * time.Millisecond,
},
Test: CheckResult{
Name: "test", Status: "pass",
Duration: 2100 * time.Millisecond,
TestCount: 12,
},
AllPassed: allPassed,
}
if !allPassed {
verify.Test.Status = "fail"
run.ExitCode = 1
}
return task, run, verify
}
func TestWriteReport_CreatesFile(t *testing.T) {
dir := t.TempDir()
reportsDir := filepath.Join(dir, "reports")
task, run, verify := makeTestData(true)
path, err := WriteReport(task, run, verify, reportsDir)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if _, err := os.Stat(path); err != nil {
t.Fatalf("report file not found: %v", err)
}
expectedFilename := "T07-report.md"
if filepath.Base(path) != expectedFilename {
t.Errorf("expected filename %s, got %s", expectedFilename, filepath.Base(path))
}
}
func TestWriteReport_Content(t *testing.T) {
dir := t.TempDir()
task, run, verify := makeTestData(true)
path, err := WriteReport(task, run, verify, dir)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
data, err := os.ReadFile(path)
if err != nil {
t.Fatalf("read report: %v", err)
}
content := string(data)
checks := []struct {
name string
substr string
}{
{"header", "# T07: Test feature"},
{"date format", "2026-02-20 10:15"},
{"duration", "8m 45s"},
{"status passed", "✅ Završen"},
{"build check", "✅ build"},
{"vet check", "✅ vet"},
{"test count", "12 testova"},
{"agent output section", "## Agent output"},
{"output content", "Task completed successfully"},
}
for _, c := range checks {
if !strings.Contains(content, c.substr) {
t.Errorf("%s: expected %q in report, got:\n%s", c.name, c.substr, content)
}
}
}
func TestWriteReport_FailedStatus(t *testing.T) {
dir := t.TempDir()
task, run, verify := makeTestData(false)
path, err := WriteReport(task, run, verify, dir)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
data, _ := os.ReadFile(path)
content := string(data)
if !strings.Contains(content, "❌ Neuspešan") {
t.Errorf("expected '❌ Neuspešan' in report, got:\n%s", content)
}
if !strings.Contains(content, "❌ test") {
t.Errorf("expected '❌ test' in report, got:\n%s", content)
}
}
func TestWriteReport_CreatesDirectory(t *testing.T) {
dir := t.TempDir()
reportsDir := filepath.Join(dir, "deep", "nested", "reports")
task, run, verify := makeTestData(true)
path, err := WriteReport(task, run, verify, reportsDir)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if _, err := os.Stat(path); err != nil {
t.Fatalf("report file not found: %v", err)
}
}
func TestTruncateOutput_Short(t *testing.T) {
output := "line1\nline2\nline3\n"
result := truncateOutput(output, 50)
if strings.Contains(result, "skraćeno") {
t.Error("should not truncate short output")
}
if !strings.Contains(result, "line1") {
t.Error("expected all lines present")
}
}
func TestTruncateOutput_Long(t *testing.T) {
var lines []string
for i := 1; i <= 80; i++ {
lines = append(lines, "line "+string(rune('0'+i/10))+string(rune('0'+i%10)))
}
output := strings.Join(lines, "\n")
result := truncateOutput(output, 50)
if !strings.Contains(result, "skraćeno") {
t.Error("expected truncation marker")
}
if !strings.Contains(result, "poslednjih 50 od 80") {
t.Errorf("expected 'poslednjih 50 od 80' in: %s", result)
}
// First lines should be gone
if strings.Contains(result, "line 01") {
t.Error("expected first lines to be removed")
}
}
func TestTruncateOutput_Empty(t *testing.T) {
result := truncateOutput("", 50)
if !strings.Contains(result, "nema outputa") {
t.Errorf("expected 'nema outputa', got: %s", result)
}
}
func TestFormatDuration_Minutes(t *testing.T) {
d := 8*time.Minute + 45*time.Second
result := formatDuration(d)
if result != "8m 45s" {
t.Errorf("expected '8m 45s', got %q", result)
}
}
func TestFormatDuration_SecondsOnly(t *testing.T) {
d := 45 * time.Second
result := formatDuration(d)
if result != "45s" {
t.Errorf("expected '45s', got %q", result)
}
}
func TestFormatDuration_Zero(t *testing.T) {
result := formatDuration(0)
if result != "0s" {
t.Errorf("expected '0s', got %q", result)
}
}