- Razbijen monolitni server_test.go na fokusirane test fajlove: api_test.go, dashboard_test.go, docs_test.go, search_test.go, submit_test.go, task_detail_test.go, console_test.go, sse_test.go, timestamp_test.go, ui_test.go, test_helpers_test.go - Dodat logs.go handler (handleLogsTail) koji je nedostajao - Dodat LogFile u config - Fix konzola: prompt se šalje preko fajla umesto direktno u PTY - 192 testova prolazi Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
273 lines
7.1 KiB
Go
273 lines
7.1 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/dal/kaos/internal/supervisor"
|
|
)
|
|
|
|
func TestTaskDetailHTML(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/task/T01", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("expected 200, got %d", w.Code)
|
|
}
|
|
|
|
body := w.Body.String()
|
|
if !containsStr(body, "T01") {
|
|
t.Error("expected T01 in detail HTML")
|
|
}
|
|
if !containsStr(body, "Prvi task") {
|
|
t.Error("expected task title in detail HTML")
|
|
}
|
|
}
|
|
|
|
func TestTaskDetailHTML_NotFound(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/task/T99", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusNotFound {
|
|
t.Fatalf("expected 404, got %d", w.Code)
|
|
}
|
|
}
|
|
|
|
func TestReport_Exists(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
// Create a report
|
|
reportsDir := filepath.Join(srv.Config.TasksDir, "reports")
|
|
os.MkdirAll(reportsDir, 0755)
|
|
os.WriteFile(filepath.Join(reportsDir, "T01-report.md"), []byte("# T01 Report\nSve ok."), 0644)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/report/T01", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("expected 200, got %d", w.Code)
|
|
}
|
|
if !containsStr(w.Body.String(), "T01 Report") {
|
|
t.Error("expected report content")
|
|
}
|
|
}
|
|
|
|
func TestReport_NotFound(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/report/T99", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusNotFound {
|
|
t.Fatalf("expected 404, got %d", w.Code)
|
|
}
|
|
}
|
|
|
|
func TestRunTask_Ready(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
// Move T08 to ready first
|
|
os.Rename(
|
|
filepath.Join(srv.Config.TasksDir, "backlog", "T08.md"),
|
|
filepath.Join(srv.Config.TasksDir, "ready", "T08.md"),
|
|
)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/task/T08/run", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String())
|
|
}
|
|
|
|
var resp map[string]interface{}
|
|
json.Unmarshal(w.Body.Bytes(), &resp)
|
|
if resp["status"] != "started" {
|
|
t.Errorf("expected status started, got %v", resp["status"])
|
|
}
|
|
if resp["task"] != "T08" {
|
|
t.Errorf("expected task T08, got %v", resp["task"])
|
|
}
|
|
// Verify task moved to active/
|
|
if _, err := os.Stat(filepath.Join(srv.Config.TasksDir, "active", "T08.md")); err != nil {
|
|
t.Error("expected T08.md in active/")
|
|
}
|
|
}
|
|
|
|
func TestRunTask_BacklogWithDeps(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
// T08 depends on T07, T01 is in done
|
|
// T08 depends on T07 which is NOT in done → should fail
|
|
req := httptest.NewRequest(http.MethodPost, "/task/T08/run", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusBadRequest {
|
|
t.Fatalf("expected 400 for unmet deps, got %d: %s", w.Code, w.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestRunTask_AlreadyDone(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
// T01 is in done
|
|
req := httptest.NewRequest(http.MethodPost, "/task/T01/run", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusBadRequest {
|
|
t.Fatalf("expected 400 for done task, got %d", w.Code)
|
|
}
|
|
}
|
|
|
|
func TestRunTask_NotFound(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/task/T99/run", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusNotFound {
|
|
t.Fatalf("expected 404, got %d", w.Code)
|
|
}
|
|
}
|
|
|
|
func TestRunTask_MovesToActive(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
// Move T08 to ready
|
|
os.Rename(
|
|
filepath.Join(srv.Config.TasksDir, "backlog", "T08.md"),
|
|
filepath.Join(srv.Config.TasksDir, "ready", "T08.md"),
|
|
)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/task/T08/run", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String())
|
|
}
|
|
|
|
// Verify task moved to active/
|
|
if _, err := os.Stat(filepath.Join(srv.Config.TasksDir, "active", "T08.md")); err != nil {
|
|
t.Error("expected T08.md in active/ after run")
|
|
}
|
|
}
|
|
|
|
func TestResolveTaskAction_Blocked(t *testing.T) {
|
|
doneSet := map[string]bool{"T01": true}
|
|
task := supervisor.Task{ID: "T08", Status: "backlog", DependsOn: []string{"T07"}}
|
|
if got := resolveTaskAction(task, doneSet); got != "blocked" {
|
|
t.Errorf("expected blocked, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestResolveTaskAction_Review(t *testing.T) {
|
|
doneSet := map[string]bool{"T07": true}
|
|
task := supervisor.Task{ID: "T08", Status: "backlog", DependsOn: []string{"T07"}}
|
|
if got := resolveTaskAction(task, doneSet); got != "review" {
|
|
t.Errorf("expected review, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestResolveTaskAction_Run(t *testing.T) {
|
|
task := supervisor.Task{ID: "T08", Status: "ready"}
|
|
if got := resolveTaskAction(task, nil); got != "run" {
|
|
t.Errorf("expected run, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestResolveTaskAction_Running(t *testing.T) {
|
|
task := supervisor.Task{ID: "T08", Status: "active"}
|
|
if got := resolveTaskAction(task, nil); got != "running" {
|
|
t.Errorf("expected running, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestResolveTaskAction_Approve(t *testing.T) {
|
|
task := supervisor.Task{ID: "T08", Status: "review"}
|
|
if got := resolveTaskAction(task, nil); got != "approve" {
|
|
t.Errorf("expected approve, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestResolveTaskAction_Done(t *testing.T) {
|
|
task := supervisor.Task{ID: "T01", Status: "done"}
|
|
if got := resolveTaskAction(task, nil); got != "done" {
|
|
t.Errorf("expected done, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestReport_RendersMarkdownInModal(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/report/T01", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("expected 200, got %d", w.Code)
|
|
}
|
|
|
|
body := w.Body.String()
|
|
if !containsStr(body, "detail-inner") {
|
|
t.Error("expected detail-inner wrapper for modal")
|
|
}
|
|
if !containsStr(body, "docs-content") {
|
|
t.Error("expected docs-content class for markdown rendering")
|
|
}
|
|
if !containsStr(body, "<h1>") {
|
|
t.Error("expected rendered markdown heading")
|
|
}
|
|
if !containsStr(body, "Izveštaj") {
|
|
t.Error("expected 'Izveštaj' in title")
|
|
}
|
|
}
|
|
|
|
func TestReport_NoReport_ShowsTask(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
// T08 has no report — should show task content
|
|
req := httptest.NewRequest(http.MethodGet, "/report/T08", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String())
|
|
}
|
|
|
|
body := w.Body.String()
|
|
if !containsStr(body, "detail-inner") {
|
|
t.Error("expected detail-inner wrapper")
|
|
}
|
|
if !containsStr(body, "HTTP server") {
|
|
t.Error("expected task title in fallback content")
|
|
}
|
|
}
|
|
|
|
func TestReport_NotFoundTask(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/report/T99", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusNotFound {
|
|
t.Fatalf("expected 404, got %d", w.Code)
|
|
}
|
|
}
|