Composition roots copy Parts once so HTTP/CLI handlers stop calling locator getters on every request. Co-authored-by: Cursor <cursoragent@cursor.com>
114 lines
3.3 KiB
Go
114 lines
3.3 KiB
Go
package server_test
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"chat-agent-system/internal/bizdev"
|
|
"chat-agent-system/internal/config"
|
|
"chat-agent-system/internal/ctxmgr"
|
|
"chat-agent-system/internal/server"
|
|
)
|
|
|
|
func TestServer_ChatSearchAndDigestAPIs(t *testing.T) {
|
|
cfg := &config.Config{
|
|
Env: "dev",
|
|
HTTPHost: "127.0.0.1",
|
|
HTTPPort: 8890,
|
|
DataDir: t.TempDir(),
|
|
}
|
|
svc := bizdev.MustNewService(t, cfg)
|
|
srv := server.NewServer(cfg, svc)
|
|
handler := srv.Routes()
|
|
|
|
sessID := "sess_api_search_digest_001"
|
|
dayKey := "2026-09-09"
|
|
|
|
// 注入种子消息
|
|
ctx := t.Context()
|
|
ctxMgr := bizdev.Snapshot(svc).Ctx
|
|
_, _ = ctxMgr.RecordUserMessageWithID(ctx, sessID, 1, "user", "我们启动超声探头研发预算,计划投入150万元", "TRIGGER_TASK", "", map[string]any{
|
|
"day_key": dayKey,
|
|
})
|
|
_, _ = ctxMgr.RecordUserMessageWithID(ctx, sessID, 0, "assistant", "已确认150万预算,主攻探头阵元与外壳生物相容性测试", "DOCGOV_REVIEW", "", map[string]any{
|
|
"day_key": dayKey,
|
|
"milestone": true,
|
|
"doc_title": "超声探头立项规格书",
|
|
})
|
|
|
|
t.Run("GET /api/v1/chat/search 正常检索", func(t *testing.T) {
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/chat/search?session_id="+sessID+"&q=150万", nil)
|
|
w := httptest.NewRecorder()
|
|
handler.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("expected 200 OK, got %d: %s", w.Code, w.Body.String())
|
|
}
|
|
|
|
var hits []ctxmgr.ChatSearchHit
|
|
if err := json.NewDecoder(w.Body).Decode(&hits); err != nil {
|
|
t.Fatalf("decode hits failed: %v", err)
|
|
}
|
|
if len(hits) != 2 {
|
|
t.Fatalf("expected 2 hits, got %d", len(hits))
|
|
}
|
|
})
|
|
|
|
t.Run("GET /api/v1/chat/search 缺少参数400拦截", func(t *testing.T) {
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/chat/search?session_id="+sessID, nil)
|
|
w := httptest.NewRecorder()
|
|
handler.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusBadRequest {
|
|
t.Errorf("expected 400 Bad Request for missing q, got %d", w.Code)
|
|
}
|
|
})
|
|
|
|
t.Run("POST /api/v1/chat/digests/generate 触发生成", func(t *testing.T) {
|
|
body := map[string]string{
|
|
"session_id": sessID,
|
|
"day_key": dayKey,
|
|
}
|
|
jsonBytes, _ := json.Marshal(body)
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/chat/digests/generate", bytes.NewReader(jsonBytes))
|
|
w := httptest.NewRecorder()
|
|
handler.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("expected 200 OK, got %d: %s", w.Code, w.Body.String())
|
|
}
|
|
|
|
var res map[string]any
|
|
if err := json.NewDecoder(w.Body).Decode(&res); err != nil {
|
|
t.Fatalf("decode generate response failed: %v", err)
|
|
}
|
|
if res["queued"] != true {
|
|
t.Errorf("expected queued=true, got %v", res["queued"])
|
|
}
|
|
})
|
|
|
|
t.Run("GET /api/v1/chat/digests 查询列表", func(t *testing.T) {
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/chat/digests?session_id="+sessID, nil)
|
|
w := httptest.NewRecorder()
|
|
handler.ServeHTTP(w, req)
|
|
|
|
if w.Code != http.StatusOK {
|
|
t.Fatalf("expected 200 OK, got %d: %s", w.Code, w.Body.String())
|
|
}
|
|
|
|
var digests []ctxmgr.DailyDigest
|
|
if err := json.NewDecoder(w.Body).Decode(&digests); err != nil {
|
|
t.Fatalf("decode digests failed: %v", err)
|
|
}
|
|
if len(digests) != 1 {
|
|
t.Fatalf("expected 1 digest, got %d", len(digests))
|
|
}
|
|
if digests[0].DayKey != dayKey {
|
|
t.Errorf("expected dayKey %s, got %s", dayKey, digests[0].DayKey)
|
|
}
|
|
})
|
|
}
|