172 lines
8.5 KiB
Go
172 lines
8.5 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.cin.su/m/Assistant/contracts/capability"
|
|
"git.cin.su/m/Assistant/contracts/cognitive"
|
|
"git.cin.su/m/Assistant/contracts/continuity"
|
|
"git.cin.su/m/Assistant/contracts/identity"
|
|
"git.cin.su/m/Assistant/contracts/interaction"
|
|
)
|
|
|
|
func TestChatPageServedWithoutInternalIDs(t *testing.T) {
|
|
handler, err := newHandler("http://core", "http://continuity", "http://commit", http.DefaultClient, "http://cognitive")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
recorder := httptest.NewRecorder()
|
|
handler.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/chat", nil))
|
|
if recorder.Code != http.StatusOK {
|
|
t.Fatalf("expected /chat status 200, got %d", recorder.Code)
|
|
}
|
|
body := recorder.Body.String()
|
|
for _, forbidden := range []string{"provider_id", "model_id", "binding_id", "workspace-id", "session-id"} {
|
|
if strings.Contains(body, forbidden) {
|
|
t.Fatalf("/chat leaks internal field %q", forbidden)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestChatMessageUsesCoreAndLocalOnlyCognitiveGateway(t *testing.T) {
|
|
var cognitiveRequest cognitive.GatewayAdvisoryRequest
|
|
core := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
switch {
|
|
case r.Method == http.MethodGet && r.URL.Path == "/v1/creator/sessions/current":
|
|
_ = json.NewEncoder(w).Encode(identity.CreatorSession{ActorID: "actor-1", PrincipalID: "principal-1"})
|
|
case r.Method == http.MethodPost && r.URL.Path == "/v1/creator/chat/messages":
|
|
var request interaction.ChatMessageRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if request.Message != "Кто ты?" || request.ConversationID != "" {
|
|
t.Fatalf("unexpected core chat request: %#v", request)
|
|
}
|
|
w.WriteHeader(http.StatusCreated)
|
|
_ = json.NewEncoder(w).Encode(interaction.ChatMessageResponse{ConversationID: "conversation-1", UtteranceID: "utterance-1", SpeechAct: interaction.SpeechActQuestion, InterpretationState: interaction.InterpretationInterpreted, NeedsCognition: true, FallbackText: "fallback"})
|
|
default:
|
|
t.Fatalf("unexpected core route %s %s", r.Method, r.URL.Path)
|
|
}
|
|
}))
|
|
defer core.Close()
|
|
continuity := httptest.NewServer(http.NotFoundHandler())
|
|
defer continuity.Close()
|
|
commit := httptest.NewServer(http.NotFoundHandler())
|
|
defer commit.Close()
|
|
cognitiveRuntime := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost || r.URL.Path != "/v1/advisories" {
|
|
t.Fatalf("unexpected cognitive route %s %s", r.Method, r.URL.Path)
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&cognitiveRequest); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_ = json.NewEncoder(w).Encode(cognitive.GatewayAdvisoryResponse{Version: cognitive.CreatorAdvisoryV1, RequestID: cognitiveRequest.RequestID, AdvisoryText: "Я Домовой.", FinishReason: cognitive.FinishCompleted, ReferencedExcerptIDs: []cognitive.ContextExcerptID{}})
|
|
}))
|
|
defer cognitiveRuntime.Close()
|
|
|
|
handler, err := newHandler(core.URL, continuity.URL, commit.URL, core.Client(), cognitiveRuntime.URL)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
request := httptest.NewRequest(http.MethodPost, "/api/chat/messages", strings.NewReader(`{"message":"Кто ты?"}`))
|
|
request.Header.Set("Authorization", "Bearer session-token")
|
|
request.Header.Set("Content-Type", "application/json")
|
|
recorder := httptest.NewRecorder()
|
|
handler.ServeHTTP(recorder, request)
|
|
if recorder.Code != http.StatusOK {
|
|
t.Fatalf("expected status 200, got %d body=%s", recorder.Code, recorder.Body.String())
|
|
}
|
|
var response browserChatResponse
|
|
if err := json.NewDecoder(recorder.Body).Decode(&response); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if response.ReplyText != "Я Домовой." || response.ConversationID != "conversation-1" || response.SpeechAct != string(interaction.SpeechActQuestion) {
|
|
t.Fatalf("unexpected chat response: %#v", response)
|
|
}
|
|
if cognitiveRequest.DataPolicy != capability.DataPolicyLocalOnly || cognitiveRequest.EgressAcknowledged {
|
|
t.Fatalf("unexpected cognitive policy: %#v", cognitiveRequest)
|
|
}
|
|
if cognitiveRequest.ActorID != "actor-1" || cognitiveRequest.PrincipalID != "principal-1" || cognitiveRequest.ScopeID != "domovoy-global-scope" || cognitiveRequest.Message != "Кто ты?" {
|
|
t.Fatalf("unexpected trusted gateway request: %#v", cognitiveRequest)
|
|
}
|
|
}
|
|
|
|
func TestChatMessageReturnsHumanCapabilityMetadata(t *testing.T) {
|
|
core := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
switch {
|
|
case r.Method == http.MethodGet && r.URL.Path == "/v1/creator/sessions/current":
|
|
_ = json.NewEncoder(w).Encode(identity.CreatorSession{ActorID: "actor-1", PrincipalID: "principal-1"})
|
|
case r.Method == http.MethodPost && r.URL.Path == "/v1/creator/chat/messages":
|
|
w.WriteHeader(http.StatusCreated)
|
|
_ = json.NewEncoder(w).Encode(interaction.ChatMessageResponse{ConversationID: "conversation-1", UtteranceID: "utterance-1", SpeechAct: interaction.SpeechActDirective, FallbackText: "fallback", PlanningReply: "Готово. Я создал напоминание: позвонить врачу.", CapabilityStatus: capability.ResolutionAvailable, CapabilityKind: capability.CapabilityKindScheduleReminder})
|
|
default:
|
|
t.Fatalf("unexpected core route %s %s", r.Method, r.URL.Path)
|
|
}
|
|
}))
|
|
defer core.Close()
|
|
handler, err := newHandler(core.URL, "http://continuity", "http://commit", core.Client(), "http://cognitive")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
request := httptest.NewRequest(http.MethodPost, "/api/chat/messages", strings.NewReader(`{"message":"Напомни завтра в 10 позвонить врачу."}`))
|
|
request.Header.Set("Authorization", "Bearer session-token")
|
|
request.Header.Set("Content-Type", "application/json")
|
|
recorder := httptest.NewRecorder()
|
|
handler.ServeHTTP(recorder, request)
|
|
if recorder.Code != http.StatusOK {
|
|
t.Fatalf("status=%d body=%s", recorder.Code, recorder.Body.String())
|
|
}
|
|
var response browserChatResponse
|
|
if err := json.NewDecoder(recorder.Body).Decode(&response); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if response.ReplyText != "Готово. Я создал напоминание: позвонить врачу." || response.CapabilityStatus != string(capability.ResolutionAvailable) || response.CapabilityKind != string(capability.CapabilityKindScheduleReminder) {
|
|
t.Fatalf("unexpected browser response: %#v", response)
|
|
}
|
|
}
|
|
|
|
func TestChatAttentionQuestionUsesContinuityToday(t *testing.T) {
|
|
core := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
switch {
|
|
case r.Method == http.MethodGet && r.URL.Path == "/v1/creator/sessions/current":
|
|
_ = json.NewEncoder(w).Encode(identity.CreatorSession{ActorID: "actor-1", PrincipalID: "principal-1"})
|
|
case r.Method == http.MethodPost && r.URL.Path == "/v1/creator/chat/messages":
|
|
w.WriteHeader(http.StatusCreated)
|
|
_ = json.NewEncoder(w).Encode(interaction.ChatMessageResponse{ConversationID: "conversation-1", UtteranceID: "utterance-1", SpeechAct: interaction.SpeechActQuestion, FallbackText: "Сейчас в фокусе: УПО."})
|
|
default:
|
|
t.Fatalf("unexpected core route %s %s", r.Method, r.URL.Path)
|
|
}
|
|
}))
|
|
defer core.Close()
|
|
continuityRuntime := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet || r.URL.Path != "/v1/creator/today" {
|
|
t.Fatalf("unexpected continuity route %s %s", r.Method, r.URL.Path)
|
|
}
|
|
_ = json.NewEncoder(w).Encode(continuity.TodayResult{Items: []continuity.TodayItem{{Title: "проверить уведомление", HumanState: "доставлено", DeliveryState: "уведомление отправлено"}}})
|
|
}))
|
|
defer continuityRuntime.Close()
|
|
handler, err := newHandler(core.URL, continuityRuntime.URL, "http://commit", core.Client(), "http://cognitive")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
request := httptest.NewRequest(http.MethodPost, "/api/chat/messages", strings.NewReader(`{"message":"Что сейчас требует моего внимания?"}`))
|
|
request.Header.Set("Authorization", "Bearer session-token")
|
|
request.Header.Set("Content-Type", "application/json")
|
|
recorder := httptest.NewRecorder()
|
|
handler.ServeHTTP(recorder, request)
|
|
if recorder.Code != http.StatusOK {
|
|
t.Fatalf("status=%d body=%s", recorder.Code, recorder.Body.String())
|
|
}
|
|
var response browserChatResponse
|
|
if err := json.NewDecoder(recorder.Body).Decode(&response); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(response.ReplyText, "проверить уведомление") || strings.Contains(response.ReplyText, "УПО") {
|
|
t.Fatalf("attention reply did not use canonical today: %#v", response)
|
|
}
|
|
}
|