yao/openapi/tests/chat/session_test.go
Max 279ae161c6 Enhance chat storage design with HTTP API documentation
- Added comprehensive documentation for the new RESTful HTTP APIs for managing chat sessions and messages, including endpoints for listing, retrieving, updating, and deleting chat sessions.
- Included detailed request and response examples for each endpoint, along with query parameters and permission filtering guidelines.
- Updated the `CHAT_STORAGE_DESIGN.md` to reflect these changes, ensuring clarity on the API's functionality and usage.
2025-12-09 16:03:17 +08:00

766 lines
25 KiB
Go

package openapi_test
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"testing"
"time"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"github.com/yaoapp/yao/agent/assistant"
storetypes "github.com/yaoapp/yao/agent/store/types"
"github.com/yaoapp/yao/openapi"
"github.com/yaoapp/yao/openapi/tests/testutils"
)
// =============================================================================
// Test Setup Helpers
// =============================================================================
// createTestChat creates a test chat session in the database
func createTestChat(t *testing.T, title string, assistantID string) string {
chatStore := assistant.GetChatStore()
if chatStore == nil {
t.Skip("Chat store not initialized")
}
chatID := uuid.New().String()
chat := &storetypes.Chat{
ChatID: chatID,
AssistantID: assistantID,
Title: title,
Status: "active",
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
}
err := chatStore.CreateChat(chat)
if err != nil {
t.Fatalf("Failed to create test chat: %v", err)
}
t.Logf("Created test chat: %s (title: %s)", chatID, title)
return chatID
}
// createTestMessage creates a test message in the database
func createTestMessage(t *testing.T, chatID, role, msgType, content string) string {
chatStore := assistant.GetChatStore()
if chatStore == nil {
t.Skip("Chat store not initialized")
}
msgID := uuid.New().String()
msg := &storetypes.Message{
MessageID: msgID,
ChatID: chatID,
Role: role,
Type: msgType,
Props: map[string]interface{}{
"content": content,
},
Sequence: 1,
CreatedAt: time.Now(),
}
err := chatStore.SaveMessages(chatID, []*storetypes.Message{msg})
if err != nil {
t.Fatalf("Failed to create test message: %v", err)
}
t.Logf("Created test message: %s (role: %s)", msgID, role)
return msgID
}
// cleanupTestChat deletes a test chat session
func cleanupTestChat(t *testing.T, chatID string) {
chatStore := assistant.GetChatStore()
if chatStore == nil {
return
}
err := chatStore.DeleteChat(chatID)
if err != nil {
t.Logf("Warning: Failed to cleanup test chat %s: %v", chatID, err)
} else {
t.Logf("Cleaned up test chat: %s", chatID)
}
}
// =============================================================================
// List Chat Sessions Tests
// =============================================================================
// TestListChatSessions tests the chat sessions listing endpoint
func TestListChatSessions(t *testing.T) {
serverURL := testutils.Prepare(t)
defer testutils.Clean()
// Get base URL from server config
baseURL := ""
if openapi.Server != nil && openapi.Server.Config != nil {
baseURL = openapi.Server.Config.BaseURL
}
// Register test client and get token
client := testutils.RegisterTestClient(t, "Chat Session Test Client", []string{"https://localhost/callback"})
defer testutils.CleanupTestClient(t, client.ClientID)
tokenInfo := testutils.ObtainAccessToken(t, serverURL, client.ClientID, client.ClientSecret, "https://localhost/callback", "openid profile")
// Create test chats
chatID1 := createTestChat(t, "Test Chat 1", "test-assistant")
defer cleanupTestChat(t, chatID1)
chatID2 := createTestChat(t, "Test Chat 2", "test-assistant")
defer cleanupTestChat(t, chatID2)
t.Run("ListChatsSuccess", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode, "Should successfully retrieve chat sessions")
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
// Check response structure
assert.Contains(t, response, "data")
assert.Contains(t, response, "page")
assert.Contains(t, response, "pagesize")
assert.Contains(t, response, "total")
data, hasData := response["data"].([]interface{})
if hasData {
t.Logf("Successfully retrieved %d chat sessions", len(data))
}
})
t.Run("ListChatsWithPagination", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions?page=1&pagesize=10", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
// Verify pagination values
page, hasPage := response["page"].(float64)
pagesize, hasPagesize := response["pagesize"].(float64)
if hasPage && hasPagesize {
assert.Equal(t, float64(1), page, "Page should be 1")
assert.Equal(t, float64(10), pagesize, "Pagesize should be 10")
t.Logf("Pagination working correctly: page=%d, pagesize=%d", int(page), int(pagesize))
}
})
t.Run("ListChatsWithKeywords", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions?keywords=Test", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
data, hasData := response["data"].([]interface{})
if hasData {
t.Logf("Successfully retrieved %d chat sessions with keywords filter", len(data))
}
})
t.Run("ListChatsWithStatusFilter", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions?status=active", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
data, hasData := response["data"].([]interface{})
if hasData {
t.Logf("Successfully retrieved %d active chat sessions", len(data))
}
})
t.Run("ListChatsWithAssistantFilter", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions?assistant_id=test-assistant", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
data, hasData := response["data"].([]interface{})
if hasData {
t.Logf("Successfully retrieved %d chat sessions with assistant filter", len(data))
}
})
t.Run("ListChatsWithTimeRange", func(t *testing.T) {
startTime := time.Now().Add(-24 * time.Hour).Format(time.RFC3339)
endTime := time.Now().Add(time.Hour).Format(time.RFC3339)
req, err := http.NewRequest("GET", fmt.Sprintf("%s%s/chat/sessions?start_time=%s&end_time=%s", serverURL, baseURL, startTime, endTime), nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
data, hasData := response["data"].([]interface{})
if hasData {
t.Logf("Successfully retrieved %d chat sessions within time range", len(data))
}
})
t.Run("ListChatsWithSorting", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions?order_by=created_at&order=desc", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
data, hasData := response["data"].([]interface{})
if hasData {
t.Logf("Successfully retrieved %d chat sessions with sorting", len(data))
}
})
t.Run("ListChatsWithGroupBy", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions?group_by=time", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
// Check for groups in response
_, hasGroups := response["groups"]
assert.True(t, hasGroups, "Response should contain groups when group_by=time")
t.Logf("Successfully retrieved chat sessions with time grouping")
})
t.Run("ListChatsUnauthorized", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions", nil)
assert.NoError(t, err)
// No Authorization header
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
// Should fail without authorization
assert.NotEqual(t, http.StatusOK, resp.StatusCode, "Should fail without authorization")
})
}
// =============================================================================
// Get Chat Session Tests
// =============================================================================
// TestGetChatSession tests the get single chat session endpoint
func TestGetChatSession(t *testing.T) {
serverURL := testutils.Prepare(t)
defer testutils.Clean()
// Get base URL from server config
baseURL := ""
if openapi.Server != nil && openapi.Server.Config != nil {
baseURL = openapi.Server.Config.BaseURL
}
// Register test client and get token
client := testutils.RegisterTestClient(t, "Chat Get Test Client", []string{"https://localhost/callback"})
defer testutils.CleanupTestClient(t, client.ClientID)
tokenInfo := testutils.ObtainAccessToken(t, serverURL, client.ClientID, client.ClientSecret, "https://localhost/callback", "openid profile")
// Create test chat
chatID := createTestChat(t, "Test Chat for Get", "test-assistant")
defer cleanupTestChat(t, chatID)
t.Run("GetChatSuccess", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions/"+chatID, nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode, "Should successfully retrieve chat session")
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
// Check response contains chat data
data, hasData := response["data"].(map[string]interface{})
if hasData {
assert.Equal(t, chatID, data["chat_id"], "Chat ID should match")
t.Logf("Successfully retrieved chat: %s", chatID)
}
})
t.Run("GetChatNotFound", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions/non-existent-chat-id", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusNotFound, resp.StatusCode, "Should return 404 for non-existent chat")
})
t.Run("GetChatUnauthorized", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions/"+chatID, nil)
assert.NoError(t, err)
// No Authorization header
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.NotEqual(t, http.StatusOK, resp.StatusCode, "Should fail without authorization")
})
}
// =============================================================================
// Update Chat Session Tests
// =============================================================================
// TestUpdateChatSession tests the update chat session endpoint
func TestUpdateChatSession(t *testing.T) {
serverURL := testutils.Prepare(t)
defer testutils.Clean()
// Get base URL from server config
baseURL := ""
if openapi.Server != nil && openapi.Server.Config != nil {
baseURL = openapi.Server.Config.BaseURL
}
// Register test client and get token
client := testutils.RegisterTestClient(t, "Chat Update Test Client", []string{"https://localhost/callback"})
defer testutils.CleanupTestClient(t, client.ClientID)
tokenInfo := testutils.ObtainAccessToken(t, serverURL, client.ClientID, client.ClientSecret, "https://localhost/callback", "openid profile")
// Create test chat
chatID := createTestChat(t, "Test Chat for Update", "test-assistant")
defer cleanupTestChat(t, chatID)
t.Run("UpdateChatTitleSuccess", func(t *testing.T) {
body := map[string]interface{}{
"title": "Updated Chat Title",
}
bodyBytes, _ := json.Marshal(body)
req, err := http.NewRequest("PUT", serverURL+baseURL+"/chat/sessions/"+chatID, bytes.NewReader(bodyBytes))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode, "Should successfully update chat title")
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
t.Logf("Successfully updated chat title: %s", chatID)
})
t.Run("UpdateChatStatusSuccess", func(t *testing.T) {
body := map[string]interface{}{
"status": "archived",
}
bodyBytes, _ := json.Marshal(body)
req, err := http.NewRequest("PUT", serverURL+baseURL+"/chat/sessions/"+chatID, bytes.NewReader(bodyBytes))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode, "Should successfully update chat status")
t.Logf("Successfully updated chat status: %s", chatID)
})
t.Run("UpdateChatMetadataSuccess", func(t *testing.T) {
body := map[string]interface{}{
"metadata": map[string]interface{}{
"custom_key": "custom_value",
},
}
bodyBytes, _ := json.Marshal(body)
req, err := http.NewRequest("PUT", serverURL+baseURL+"/chat/sessions/"+chatID, bytes.NewReader(bodyBytes))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode, "Should successfully update chat metadata")
t.Logf("Successfully updated chat metadata: %s", chatID)
})
t.Run("UpdateChatNoFields", func(t *testing.T) {
body := map[string]interface{}{}
bodyBytes, _ := json.Marshal(body)
req, err := http.NewRequest("PUT", serverURL+baseURL+"/chat/sessions/"+chatID, bytes.NewReader(bodyBytes))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
// Note: Server may still return 200 if it adds __yao_updated_by automatically
// This is acceptable behavior - the update still happens with the updater field
assert.Contains(t, []int{http.StatusOK, http.StatusBadRequest}, resp.StatusCode, "Should either succeed with auto-fields or fail with no fields")
})
t.Run("UpdateChatNotFound", func(t *testing.T) {
body := map[string]interface{}{
"title": "Updated Title",
}
bodyBytes, _ := json.Marshal(body)
req, err := http.NewRequest("PUT", serverURL+baseURL+"/chat/sessions/non-existent-chat-id", bytes.NewReader(bodyBytes))
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
// Should fail for non-existent chat
assert.NotEqual(t, http.StatusOK, resp.StatusCode, "Should fail for non-existent chat")
})
t.Run("UpdateChatUnauthorized", func(t *testing.T) {
body := map[string]interface{}{
"title": "Updated Title",
}
bodyBytes, _ := json.Marshal(body)
req, err := http.NewRequest("PUT", serverURL+baseURL+"/chat/sessions/"+chatID, bytes.NewReader(bodyBytes))
assert.NoError(t, err)
req.Header.Set("Content-Type", "application/json")
// No Authorization header
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.NotEqual(t, http.StatusOK, resp.StatusCode, "Should fail without authorization")
})
}
// =============================================================================
// Delete Chat Session Tests
// =============================================================================
// TestDeleteChatSession tests the delete chat session endpoint
func TestDeleteChatSession(t *testing.T) {
serverURL := testutils.Prepare(t)
defer testutils.Clean()
// Get base URL from server config
baseURL := ""
if openapi.Server != nil && openapi.Server.Config != nil {
baseURL = openapi.Server.Config.BaseURL
}
// Register test client and get token
client := testutils.RegisterTestClient(t, "Chat Delete Test Client", []string{"https://localhost/callback"})
defer testutils.CleanupTestClient(t, client.ClientID)
tokenInfo := testutils.ObtainAccessToken(t, serverURL, client.ClientID, client.ClientSecret, "https://localhost/callback", "openid profile")
t.Run("DeleteChatSuccess", func(t *testing.T) {
// Create a chat to delete
chatID := createTestChat(t, "Test Chat for Delete", "test-assistant")
req, err := http.NewRequest("DELETE", serverURL+baseURL+"/chat/sessions/"+chatID, nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode, "Should successfully delete chat session")
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
t.Logf("Successfully deleted chat: %s", chatID)
})
t.Run("DeleteChatNotFound", func(t *testing.T) {
req, err := http.NewRequest("DELETE", serverURL+baseURL+"/chat/sessions/non-existent-chat-id", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
// Should fail for non-existent chat
assert.NotEqual(t, http.StatusOK, resp.StatusCode, "Should fail for non-existent chat")
})
t.Run("DeleteChatUnauthorized", func(t *testing.T) {
// Create a chat to attempt to delete
chatID := createTestChat(t, "Test Chat for Unauthorized Delete", "test-assistant")
defer cleanupTestChat(t, chatID)
req, err := http.NewRequest("DELETE", serverURL+baseURL+"/chat/sessions/"+chatID, nil)
assert.NoError(t, err)
// No Authorization header
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.NotEqual(t, http.StatusOK, resp.StatusCode, "Should fail without authorization")
})
}
// =============================================================================
// Get Messages Tests
// =============================================================================
// TestGetMessages tests the get messages endpoint
func TestGetMessages(t *testing.T) {
serverURL := testutils.Prepare(t)
defer testutils.Clean()
// Get base URL from server config
baseURL := ""
if openapi.Server != nil && openapi.Server.Config != nil {
baseURL = openapi.Server.Config.BaseURL
}
// Register test client and get token
client := testutils.RegisterTestClient(t, "Chat Messages Test Client", []string{"https://localhost/callback"})
defer testutils.CleanupTestClient(t, client.ClientID)
tokenInfo := testutils.ObtainAccessToken(t, serverURL, client.ClientID, client.ClientSecret, "https://localhost/callback", "openid profile")
// Create test chat with messages
chatID := createTestChat(t, "Test Chat for Messages", "test-assistant")
defer cleanupTestChat(t, chatID)
// Create test messages
createTestMessage(t, chatID, "user", "text", "Hello, how are you?")
createTestMessage(t, chatID, "assistant", "text", "I'm doing well, thank you!")
t.Run("GetMessagesSuccess", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions/"+chatID+"/messages", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode, "Should successfully retrieve messages")
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
// Check response structure
data, hasData := response["data"].(map[string]interface{})
if hasData {
messages, hasMessages := data["messages"].([]interface{})
if hasMessages {
t.Logf("Successfully retrieved %d messages", len(messages))
}
}
})
t.Run("GetMessagesWithRoleFilter", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions/"+chatID+"/messages?role=user", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
t.Logf("Successfully retrieved messages with role filter")
})
t.Run("GetMessagesWithTypeFilter", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions/"+chatID+"/messages?type=text", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
t.Logf("Successfully retrieved messages with type filter")
})
t.Run("GetMessagesWithPagination", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions/"+chatID+"/messages?limit=10&offset=0", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.Equal(t, http.StatusOK, resp.StatusCode)
var response map[string]interface{}
err = json.NewDecoder(resp.Body).Decode(&response)
assert.NoError(t, err)
t.Logf("Successfully retrieved messages with pagination")
})
t.Run("GetMessagesNotFound", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions/non-existent-chat-id/messages", nil)
assert.NoError(t, err)
req.Header.Set("Authorization", "Bearer "+tokenInfo.AccessToken)
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
// For non-existent chat, the API may return:
// - 200 with empty messages (if permission check passes first)
// - 403 Forbidden (if permission check fails on non-existent chat)
// - 404 Not Found (if explicitly checking chat existence)
// All are acceptable behaviors depending on implementation
t.Logf("Response status for non-existent chat messages: %d", resp.StatusCode)
})
t.Run("GetMessagesUnauthorized", func(t *testing.T) {
req, err := http.NewRequest("GET", serverURL+baseURL+"/chat/sessions/"+chatID+"/messages", nil)
assert.NoError(t, err)
// No Authorization header
resp, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotNil(t, resp)
defer resp.Body.Close()
assert.NotEqual(t, http.StatusOK, resp.StatusCode, "Should fail without authorization")
})
}