package server import ( "encoding/json" "net/http" "net/http/httptest" "os" "path/filepath" "strings" "testing" "github.com/dal/kaos/internal/supervisor" ) func TestSubmitPage(t *testing.T) { srv := setupTestServer(t) req := httptest.NewRequest(http.MethodGet, "/submit", 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, "Klijent") { t.Error("expected 'Klijent' mode button") } if !containsStr(body, "Operater") { t.Error("expected 'Operater' mode button") } if !containsStr(body, "mode-client") { t.Error("expected client mode section") } } func TestSubmitPage_ClientModeIsDefault(t *testing.T) { srv := setupTestServer(t) req := httptest.NewRequest(http.MethodGet, "/submit", nil) w := httptest.NewRecorder() srv.Router.ServeHTTP(w, req) body := w.Body.String() // Operator mode should be hidden by default if !containsStr(body, `id="mode-operator" class="submit-mode" style="display:none"`) { t.Error("expected operator mode to be hidden by default") } } func TestSimpleSubmit_CreatesTask(t *testing.T) { srv := setupTestServer(t) form := strings.NewReader("title=Test+prijava&description=Opis+testa&priority=Visok") req := httptest.NewRequest(http.MethodPost, "/submit/simple", form) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") 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"] != "ok" { t.Errorf("expected status ok, got %v", resp["status"]) } taskID, ok := resp["task_id"].(string) if !ok || taskID == "" { t.Fatal("expected non-empty task_id") } // Verify file was created in backlog path := filepath.Join(srv.Config.TasksDir, "backlog", taskID+".md") content, err := os.ReadFile(path) if err != nil { t.Fatalf("expected task file in backlog: %v", err) } if !containsStr(string(content), "Test prijava") { t.Error("expected title in task file") } if !containsStr(string(content), "Visok") { t.Error("expected priority in task file") } if !containsStr(string(content), "klijent (prijava)") { t.Error("expected 'klijent (prijava)' as creator") } } func TestSimpleSubmit_MissingTitle(t *testing.T) { srv := setupTestServer(t) form := strings.NewReader("description=Samo+opis") req := httptest.NewRequest(http.MethodPost, "/submit/simple", form) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") w := httptest.NewRecorder() srv.Router.ServeHTTP(w, req) if w.Code != http.StatusBadRequest { t.Fatalf("expected 400 for missing title, got %d", w.Code) } } func TestSimpleSubmit_AutoNumbering(t *testing.T) { srv := setupTestServer(t) // Existing tasks: T01 (done), T08 (backlog) // Next should be T09 form := strings.NewReader("title=Novi+task&priority=Srednji") req := httptest.NewRequest(http.MethodPost, "/submit/simple", form) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") w := httptest.NewRecorder() srv.Router.ServeHTTP(w, req) var resp map[string]interface{} json.Unmarshal(w.Body.Bytes(), &resp) taskID, _ := resp["task_id"].(string) if taskID != "T09" { t.Errorf("expected T09 (next after T08), got %s", taskID) } } func TestSimpleSubmit_DefaultPriority(t *testing.T) { srv := setupTestServer(t) form := strings.NewReader("title=Bez+prioriteta") req := httptest.NewRequest(http.MethodPost, "/submit/simple", form) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") w := httptest.NewRecorder() srv.Router.ServeHTTP(w, req) var resp map[string]interface{} json.Unmarshal(w.Body.Bytes(), &resp) taskID, _ := resp["task_id"].(string) path := filepath.Join(srv.Config.TasksDir, "backlog", taskID+".md") content, _ := os.ReadFile(path) if !containsStr(string(content), "Srednji") { t.Error("expected default priority 'Srednji'") } } func TestChatSubmit_ReturnsChatID(t *testing.T) { srv := setupTestServer(t) body := `{"message":"test poruka"}` req := httptest.NewRequest(http.MethodPost, "/submit/chat", strings.NewReader(body)) req.Header.Set("Content-Type", "application/json") 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["chat_id"] == nil || resp["chat_id"] == "" { t.Error("expected non-empty chat_id in response") } } func TestChatSubmit_EmptyMessage(t *testing.T) { srv := setupTestServer(t) body := `{"message":""}` req := httptest.NewRequest(http.MethodPost, "/submit/chat", strings.NewReader(body)) req.Header.Set("Content-Type", "application/json") w := httptest.NewRecorder() srv.Router.ServeHTTP(w, req) if w.Code != http.StatusBadRequest { t.Fatalf("expected 400 for empty message, got %d", w.Code) } } func TestChatStream_NotFound(t *testing.T) { srv := setupTestServer(t) req := httptest.NewRequest(http.MethodGet, "/submit/chat/stream/nonexistent", nil) w := httptest.NewRecorder() srv.Router.ServeHTTP(w, req) if w.Code != http.StatusNotFound { t.Fatalf("expected 404, got %d", w.Code) } } func TestNextTaskNumber(t *testing.T) { dir := t.TempDir() tasksDir := filepath.Join(dir, "TASKS") for _, f := range []string{"backlog", "ready", "active", "review", "done"} { os.MkdirAll(filepath.Join(tasksDir, f), 0755) } os.WriteFile(filepath.Join(tasksDir, "done", "T01.md"), []byte(testTask1), 0644) os.WriteFile(filepath.Join(tasksDir, "backlog", "T08.md"), []byte(testTask2), 0644) num, err := nextTaskNumber(tasksDir) if err != nil { t.Fatalf("unexpected error: %v", err) } if num != "T09" { t.Errorf("expected T09, got %s", num) } } func TestBuildTaskContext(t *testing.T) { tasks := []supervisor.Task{ {ID: "T01", Title: "Init", Status: "done", Agent: "coder", Model: "Sonnet"}, {ID: "T02", Title: "Server", Status: "active", Agent: "coder", Model: "Opus"}, } ctx := buildTaskContext(tasks) if !containsStr(ctx, "T01: Init") { t.Error("expected T01 in context") } if !containsStr(ctx, "T02: Server") { t.Error("expected T02 in context") } if !containsStr(ctx, "DONE") { t.Error("expected DONE section") } } func TestSubmitPage_HasPrijavaNav(t *testing.T) { srv := setupTestServer(t) req := httptest.NewRequest(http.MethodGet, "/submit", nil) w := httptest.NewRecorder() srv.Router.ServeHTTP(w, req) body := w.Body.String() if !containsStr(body, `href="/submit"`) { t.Error("expected Prijava nav link") } }