- 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>
206 lines
5.3 KiB
Go
206 lines
5.3 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func TestAPIGetTasks(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/tasks", 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 tasks []taskResponse
|
|
if err := json.Unmarshal(w.Body.Bytes(), &tasks); err != nil {
|
|
t.Fatalf("invalid JSON: %v", err)
|
|
}
|
|
|
|
if len(tasks) != 2 {
|
|
t.Fatalf("expected 2 tasks, got %d", len(tasks))
|
|
}
|
|
|
|
// Check that tasks have correct statuses
|
|
statuses := map[string]string{}
|
|
for _, task := range tasks {
|
|
statuses[task.ID] = task.Status
|
|
}
|
|
if statuses["T01"] != "done" {
|
|
t.Errorf("expected T01 status done, got %s", statuses["T01"])
|
|
}
|
|
if statuses["T08"] != "backlog" {
|
|
t.Errorf("expected T08 status backlog, got %s", statuses["T08"])
|
|
}
|
|
}
|
|
|
|
func TestAPIGetTask(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/task/T01", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("expected 200, got %d", w.Code)
|
|
}
|
|
|
|
var detail taskDetailResponse
|
|
if err := json.Unmarshal(w.Body.Bytes(), &detail); err != nil {
|
|
t.Fatalf("invalid JSON: %v", err)
|
|
}
|
|
|
|
if detail.ID != "T01" {
|
|
t.Errorf("expected T01, got %s", detail.ID)
|
|
}
|
|
if detail.Content == "" {
|
|
t.Error("expected non-empty content")
|
|
}
|
|
}
|
|
|
|
func TestAPIGetTask_NotFound(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/api/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 TestAPIMoveTask(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/api/task/T08/move?to=ready", 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 file was moved
|
|
if _, err := os.Stat(filepath.Join(srv.Config.TasksDir, "ready", "T08.md")); err != nil {
|
|
t.Error("expected T08.md in ready/")
|
|
}
|
|
if _, err := os.Stat(filepath.Join(srv.Config.TasksDir, "backlog", "T08.md")); !os.IsNotExist(err) {
|
|
t.Error("expected T08.md removed from backlog/")
|
|
}
|
|
}
|
|
|
|
func TestAPIMoveTask_NotFound(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/api/task/T99/move?to=ready", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusNotFound {
|
|
t.Fatalf("expected 404, got %d", w.Code)
|
|
}
|
|
}
|
|
|
|
func TestAPIMoveTask_InvalidFolder(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/api/task/T08/move?to=invalid", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusBadRequest {
|
|
t.Fatalf("expected 400, got %d", w.Code)
|
|
}
|
|
}
|
|
|
|
func TestAPIMoveTask_ForbiddenToActive(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
// Put T08 in ready first
|
|
os.Rename(
|
|
filepath.Join(srv.Config.TasksDir, "backlog", "T08.md"),
|
|
filepath.Join(srv.Config.TasksDir, "ready", "T08.md"),
|
|
)
|
|
|
|
// Try to move ready → active (agent-only)
|
|
req := httptest.NewRequest(http.MethodPost, "/api/task/T08/move?to=active", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusForbidden {
|
|
t.Fatalf("expected 403 for ready→active, got %d: %s", w.Code, w.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestAPIMoveTask_ForbiddenActiveToReview(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
// Put T08 in active
|
|
os.Rename(
|
|
filepath.Join(srv.Config.TasksDir, "backlog", "T08.md"),
|
|
filepath.Join(srv.Config.TasksDir, "active", "T08.md"),
|
|
)
|
|
|
|
// Try to move active → review (agent-only)
|
|
req := httptest.NewRequest(http.MethodPost, "/api/task/T08/move?to=review", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusForbidden {
|
|
t.Fatalf("expected 403 for active→review, got %d: %s", w.Code, w.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestAPIMoveTask_AllowedBacklogToReady(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/api/task/T08/move?to=ready", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("expected 200 for backlog→ready, got %d: %s", w.Code, w.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestAPIMoveTask_AllowedReviewToDone(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
// Put T08 in review
|
|
os.Rename(
|
|
filepath.Join(srv.Config.TasksDir, "backlog", "T08.md"),
|
|
filepath.Join(srv.Config.TasksDir, "review", "T08.md"),
|
|
)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/api/task/T08/move?to=done", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("expected 200 for review→done, got %d: %s", w.Code, w.Body.String())
|
|
}
|
|
}
|
|
|
|
func TestAPIMoveTask_AddsTimestamp(t *testing.T) {
|
|
srv := setupTestServer(t)
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/api/task/T08/move?to=ready", nil)
|
|
w := httptest.NewRecorder()
|
|
srv.Router.ServeHTTP(w, req)
|
|
|
|
content, _ := os.ReadFile(filepath.Join(srv.Config.TasksDir, "ready", "T08.md"))
|
|
text := string(content)
|
|
if !containsStr(text, "Odobren (→ready)") {
|
|
t.Error("expected timestamp in API-moved task file")
|
|
}
|
|
}
|