Files
2026-08-13 10:44:16 +08:00

107 lines
3.7 KiB
Go

package httpapi
import (
"context"
"net/http"
"net/http/httptest"
"strings"
"testing"
"gitea.zheromiku.top/Weknora/dobotai-platform/internal/core"
)
type fakeQA struct{}
func (fakeQA) Ask(context.Context, core.QARequest) (core.QAResult, error) {
return core.QAResult{TurnID: "turn-1", Answer: "answer"}, nil
}
type captureQA struct {
request core.QARequest
}
func (f *captureQA) Ask(_ context.Context, request core.QARequest) (core.QAResult, error) {
f.request = request
return core.QAResult{TurnID: "turn-capture", Answer: "answer"}, nil
}
func TestVersionEndpointReturnsBuildMetadataWithoutAuthentication(t *testing.T) {
server, err := NewWithOptions(fakeQA{}, "ingress-secret", Options{
BuildInfo: BuildInfo{
Version: "2.1.0",
CommitSHA: "abc123def456",
BuildTime: "2026-07-27T12:00:00Z",
},
})
if err != nil {
t.Fatal(err)
}
request := httptest.NewRequest(http.MethodGet, "/version", nil)
result := httptest.NewRecorder()
server.Handler().ServeHTTP(result, request)
if result.Code != http.StatusOK {
t.Fatalf("status=%d body=%s", result.Code, result.Body.String())
}
if got := result.Header().Get("Cache-Control"); got != "no-store" {
t.Fatalf("Cache-Control=%q, want no-store", got)
}
want := `{"version":"2.1.0","commit_sha":"abc123def456","build_time":"2026-07-27T12:00:00Z"}`
if got := strings.TrimSpace(result.Body.String()); got != want {
t.Fatalf("body=%s, want %s", got, want)
}
}
func TestVersionEndpointUsesSafeDefaults(t *testing.T) {
server, err := New(fakeQA{}, "ingress-secret")
if err != nil {
t.Fatal(err)
}
request := httptest.NewRequest(http.MethodGet, "/version", nil)
result := httptest.NewRecorder()
server.Handler().ServeHTTP(result, request)
want := `{"version":"dev","commit_sha":"unknown","build_time":"unknown"}`
if got := strings.TrimSpace(result.Body.String()); result.Code != http.StatusOK || got != want {
t.Fatalf("status=%d body=%s, want %s", result.Code, got, want)
}
}
func TestQAEndpointRequiresTokenAndReturnsResult(t *testing.T) {
server, err := New(fakeQA{}, "ingress-secret")
if err != nil {
t.Fatal(err)
}
body := `{"tenant_key":"tenant","channel":"dingtalk","conversation_type":"direct","external_user_id":"user","external_message_id":"message","query":"hello"}`
unauthorized := httptest.NewRequest(http.MethodPost, "/v1/qa", strings.NewReader(body))
unauthorizedResult := httptest.NewRecorder()
server.Handler().ServeHTTP(unauthorizedResult, unauthorized)
if unauthorizedResult.Code != http.StatusUnauthorized {
t.Fatalf("unauthorized status=%d", unauthorizedResult.Code)
}
authorized := httptest.NewRequest(http.MethodPost, "/v1/qa", strings.NewReader(body))
authorized.Header.Set("Authorization", "Bearer ingress-secret")
result := httptest.NewRecorder()
server.Handler().ServeHTTP(result, authorized)
if result.Code != http.StatusOK || !strings.Contains(result.Body.String(), `"turn_id":"turn-1"`) {
t.Fatalf("status=%d body=%s", result.Code, result.Body.String())
}
}
func TestQAEndpointPassesOptionalMessageType(t *testing.T) {
qa := &captureQA{}
server, err := New(qa, "ingress-secret")
if err != nil {
t.Fatal(err)
}
body := `{"tenant_key":"tenant","channel":"web","conversation_type":"direct","external_user_id":"user","external_message_id":"message-rich","message_type":"rich_text","query":"hello"}`
request := httptest.NewRequest(http.MethodPost, "/v1/qa", strings.NewReader(body))
request.Header.Set("Authorization", "Bearer ingress-secret")
result := httptest.NewRecorder()
server.Handler().ServeHTTP(result, request)
if result.Code != http.StatusOK {
t.Fatalf("status=%d body=%s", result.Code, result.Body.String())
}
if qa.request.MessageType != "rich_text" {
t.Fatalf("MessageType=%q, want rich_text", qa.request.MessageType)
}
}