5.6 KB
chat_test.go
package controllers
import (
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"github.com/readysite/readysite/website/models"
)
// Test database setup is handled by testhelper_test.go
func TestChatController_NewConversationWithMessage(t *testing.T) {
formData := url.Values{
"content": {"Create a new blog page"},
}
req := httptest.NewRequest("POST", "/admin/chat/new", strings.NewReader(formData.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
w := httptest.NewRecorder()
c := testChatController()
handler := c.Handle(req)
handler.(*ChatController).NewConversationWithMessage(w, req)
// Should either redirect or render HTML
if w.Code != http.StatusSeeOther && w.Code != http.StatusOK {
t.Errorf("NewConversationWithMessage() status = %d, want redirect or success", w.Code)
}
}
func TestChatController_SendMessage(t *testing.T) {
// Create a conversation first
conv := &models.Conversation{
Title: "Test Conversation",
}
conv.ID = "test-conv-send"
models.Conversations.Insert(conv)
formData := url.Values{
"content": {"Update the homepage"},
}
req := httptest.NewRequest("POST", "/admin/chat/test-conv-send", strings.NewReader(formData.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.SetPathValue("id", "test-conv-send")
w := httptest.NewRecorder()
c := testChatController()
handler := c.Handle(req)
handler.(*ChatController).SendMessage(w, req)
// Check that a message was created
messages, _ := models.Messages.Search("WHERE ConversationID = ?", "test-conv-send")
if len(messages) == 0 {
t.Error("Message should be created")
}
}
func TestChatController_DeleteConversation(t *testing.T) {
// Create a conversation
conv := &models.Conversation{
Title: "To Delete",
}
conv.ID = "delete-conv"
models.Conversations.Insert(conv)
// Add a message
msg := &models.Message{
ConversationID: "delete-conv",
Role: "user",
Content: "Test message",
}
models.Messages.Insert(msg)
req := httptest.NewRequest("DELETE", "/admin/chat/delete-conv", nil)
req.SetPathValue("id", "delete-conv")
w := httptest.NewRecorder()
c := testChatController()
handler := c.Handle(req)
handler.(*ChatController).Delete(w, req)
// Verify deletion
_, err := models.Conversations.Get("delete-conv")
if err == nil {
t.Error("Conversation should be deleted")
}
// Verify messages deleted too
messages, _ := models.Messages.Search("WHERE ConversationID = ?", "delete-conv")
if len(messages) > 0 {
t.Error("Messages should be deleted with conversation")
}
}
func TestChatController_TitleTruncation(t *testing.T) {
longMessage := strings.Repeat("Hello world ", 20) // 240 chars
formData := url.Values{
"content": {longMessage},
}
req := httptest.NewRequest("POST", "/admin/chat/new", strings.NewReader(formData.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
w := httptest.NewRecorder()
c := testChatController()
handler := c.Handle(req)
handler.(*ChatController).NewConversationWithMessage(w, req)
// Check that conversation title is truncated
convs, _ := models.Conversations.All()
for _, conv := range convs {
if len(conv.Title) > 53 { // 50 + "..."
t.Errorf("Title should be truncated, got %d chars", len(conv.Title))
}
}
}
func TestChatController_EmptyMessage(t *testing.T) {
formData := url.Values{
"content": {""},
}
req := httptest.NewRequest("POST", "/admin/chat/new", strings.NewReader(formData.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
w := httptest.NewRecorder()
c := testChatController()
handler := c.Handle(req)
handler.(*ChatController).NewConversationWithMessage(w, req)
// Empty message should not create conversation (or should return error)
// The exact behavior depends on implementation
_ = w // Use w to avoid unused variable warning
}
func TestChatController_ConversationsList(t *testing.T) {
// Create multiple conversations
for i := 0; i < 5; i++ {
conv := &models.Conversation{
Title: "TestConv " + string(rune('A'+i)),
}
models.Conversations.Insert(conv)
}
req := httptest.NewRequest("GET", "/admin/chat", nil)
_, c := Chat()
handler := c.Handle(req)
// Access template method
cc := handler.(*ChatController)
convs := cc.Conversations()
if len(convs) < 5 {
t.Errorf("Conversations() = %d items, want at least 5", len(convs))
}
}
func TestChatController_UndoRedo(t *testing.T) {
// Create conversation with message and mutation (use unique IDs)
conv := &models.Conversation{
Title: "Undo Test",
UserID: "test-admin-user", // Associate with test admin
}
conv.ID = "undo-conv-test-unique"
models.Conversations.Insert(conv)
msg := &models.Message{
ConversationID: "undo-conv-test-unique",
Role: "assistant",
Content: "Created page",
Status: "complete",
}
msg.ID = "undo-msg-test-unique"
models.Messages.Insert(msg)
mutation := &models.Mutation{
MessageID: "undo-msg-test-unique",
Action: "create",
EntityType: "page",
EntityID: "test-page-undo",
AfterState: `{"id":"test-page-undo","title":"Test"}`,
BeforeState: "",
Undone: false,
}
models.Mutations.Insert(mutation)
// Check CanUndo - requires authentication
c := testChatController()
req := httptest.NewRequest("GET", "/admin/chat/undo-conv-test-unique", nil)
req.SetPathValue("id", "undo-conv-test-unique")
authenticateRequest(req)
handler := c.Handle(req)
cc := handler.(*ChatController)
canUndo := cc.CanUndo()
if !canUndo {
t.Error("CanUndo() should return true when there are undoable mutations")
}
canRedo := cc.CanRedo()
if canRedo {
t.Error("CanRedo() should return false when nothing is undone")
}
}