Files
Agent-System/internal/engineeringdashboard/server_test.go
T
weichenandCursor e251ce325a feat(engineering-dashboard): U6-U7 serve UI and offline export
Add loopback-only HTTP server with startup token, Host/Origin/CSP
guards, embedded live UI, CLI serve/export, and safe single-file HTML.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 07:08:27 +00:00

131 lines
3.9 KiB
Go

package engineeringdashboard
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
)
func TestServer_RejectsNonGETAndBadHost(t *testing.T) {
c := NewCollector(t.TempDir(), &FakeRunner{Map: map[string]FakeResult{}})
c.mu.Lock()
c.current = &Snapshot{
SchemaVersion: SchemaVersion, GenerationID: "gen_1", RevisionID: "rev_1",
GeneratedAt: time.Now().UTC(), Repository: RepositoryIdentity{Root: "/r"},
}
c.mu.Unlock()
srv, err := NewServer(c)
if err != nil {
t.Fatal(err)
}
h := srv.Handler()
req := httptest.NewRequest(http.MethodPost, "/api/v1/snapshot?token="+srv.Token, nil)
req.Host = "127.0.0.1:8787"
rr := httptest.NewRecorder()
h.ServeHTTP(rr, req)
if rr.Code != http.StatusMethodNotAllowed {
t.Fatalf("POST: %d", rr.Code)
}
req = httptest.NewRequest(http.MethodGet, "/api/v1/snapshot?token="+srv.Token, nil)
req.Host = "evil.example"
rr = httptest.NewRecorder()
h.ServeHTTP(rr, req)
if rr.Code != http.StatusForbidden {
t.Fatalf("bad host: %d", rr.Code)
}
}
func TestServer_TokenAndSnapshotIdentity(t *testing.T) {
c := NewCollector(t.TempDir(), &FakeRunner{Map: map[string]FakeResult{}})
snap := Snapshot{
SchemaVersion: SchemaVersion, GenerationID: "gen_9", RevisionID: "rev_abc",
GeneratedAt: time.Now().UTC(), Repository: RepositoryIdentity{Root: "/repo", Branch: "dev", Head: "h"},
Tasks: []TaskState{SampleRDevTaskFixture()},
}
c.mu.Lock()
c.current = &snap
c.mu.Unlock()
srv, err := NewServer(c)
if err != nil {
t.Fatal(err)
}
h := srv.Handler()
req := httptest.NewRequest(http.MethodGet, "/api/v1/snapshot", nil)
req.Host = "127.0.0.1:8787"
rr := httptest.NewRecorder()
h.ServeHTTP(rr, req)
if rr.Code != http.StatusUnauthorized {
t.Fatalf("no token: %d", rr.Code)
}
req = httptest.NewRequest(http.MethodGet, "/api/v1/snapshot?token="+srv.Token, nil)
req.Host = "127.0.0.1:8787"
rr = httptest.NewRecorder()
h.ServeHTTP(rr, req)
if rr.Code != 200 {
t.Fatalf("snapshot: %d %s", rr.Code, rr.Body.String())
}
body := rr.Body.String()
if !strings.Contains(body, `"generation_id": "gen_9"`) || !strings.Contains(body, `"revision_id": "rev_abc"`) {
t.Fatalf("identity missing: %s", body)
}
if rr.Header().Get("ETag") != `"rev_abc"` {
t.Fatalf("etag %q", rr.Header().Get("ETag"))
}
req = httptest.NewRequest(http.MethodGet, "/api/v1/snapshot?token="+srv.Token, nil)
req.Host = "127.0.0.1:8787"
req.Header.Set("If-None-Match", `"rev_abc"`)
rr = httptest.NewRecorder()
h.ServeHTTP(rr, req)
if rr.Code != http.StatusNotModified {
t.Fatalf("etag: %d", rr.Code)
}
}
func TestServer_DocPathTraversalDenied(t *testing.T) {
root := t.TempDir()
writeDoc(t, root, ".doc/ops/ok.md", "# ok\n")
c := NewCollector(root, &FakeRunner{Map: map[string]FakeResult{}})
srv, err := NewServer(c)
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest(http.MethodGet, "/api/v1/doc/not-a-real.md?token="+srv.Token, nil)
req.Host = "127.0.0.1:8787"
req.URL.Path = "/api/v1/doc/../../.env"
rr := httptest.NewRecorder()
srv.Handler().ServeHTTP(rr, req)
if rr.Code != http.StatusForbidden {
t.Fatalf("got %d body=%s", rr.Code, rr.Body.String())
}
}
func TestListenAndServe_RejectsNonLoopback(t *testing.T) {
err := ListenAndServe("0.0.0.0:8787", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
if err == nil || !strings.Contains(err.Error(), "loopback") {
t.Fatalf("expected loopback reject, got %v", err)
}
}
func TestServer_CrossOriginDenied(t *testing.T) {
c := NewCollector(t.TempDir(), &FakeRunner{})
c.mu.Lock()
c.current = &Snapshot{RevisionID: "r", GenerationID: "g", GeneratedAt: time.Now().UTC()}
c.mu.Unlock()
srv, _ := NewServer(c)
req := httptest.NewRequest(http.MethodGet, "/api/v1/snapshot?token="+srv.Token, nil)
req.Host = "127.0.0.1:8787"
req.Header.Set("Origin", "https://evil.example")
rr := httptest.NewRecorder()
srv.Handler().ServeHTTP(rr, req)
if rr.Code != http.StatusForbidden {
t.Fatalf("got %d", rr.Code)
}
}