204 lines
5.7 KiB
Go
204 lines
5.7 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"os"
|
|
"testing"
|
|
|
|
"git.gobha.me/xcaliber/chat-switchboard/database"
|
|
)
|
|
|
|
func TestMain(m *testing.M) {
|
|
teardown := database.SetupTestDB()
|
|
code := m.Run()
|
|
teardown()
|
|
os.Exit(code)
|
|
}
|
|
|
|
// ── Note Tool Execution (requires DB) ───────
|
|
|
|
func TestNoteCreateExecute(t *testing.T) {
|
|
database.RequireTestDB(t)
|
|
database.TruncateAll(t)
|
|
|
|
userID := database.SeedTestUser(t, "tooluser", "tool@test.com")
|
|
channelID := database.SeedTestChannel(t, userID, "Tool Test")
|
|
|
|
ctx := context.Background()
|
|
execCtx := ExecutionContext{UserID: userID, ChannelID: channelID}
|
|
|
|
tool := Get("note_create")
|
|
if tool == nil {
|
|
t.Fatal("note_create not registered")
|
|
}
|
|
|
|
args := `{"title":"Test Note","content":"Created via tool","folder":"/tools","tags":["test","ci"]}`
|
|
result, err := tool.Execute(ctx, execCtx, args)
|
|
if err != nil {
|
|
t.Fatalf("Execute: %v", err)
|
|
}
|
|
|
|
var resp map[string]interface{}
|
|
if err := json.Unmarshal([]byte(result), &resp); err != nil {
|
|
t.Fatalf("Invalid JSON result: %v\nRaw: %s", err, result)
|
|
}
|
|
|
|
if resp["id"] == nil || resp["id"] == "" {
|
|
t.Error("Expected id in result")
|
|
}
|
|
if resp["title"] != "Test Note" {
|
|
t.Errorf("Expected title='Test Note', got %v", resp["title"])
|
|
}
|
|
}
|
|
|
|
func TestNoteListExecute(t *testing.T) {
|
|
database.RequireTestDB(t)
|
|
database.TruncateAll(t)
|
|
|
|
userID := database.SeedTestUser(t, "listuser", "list@test.com")
|
|
channelID := database.SeedTestChannel(t, userID, "List Test")
|
|
|
|
ctx := context.Background()
|
|
execCtx := ExecutionContext{UserID: userID, ChannelID: channelID}
|
|
|
|
// Create two notes first
|
|
createTool := Get("note_create")
|
|
createTool.Execute(ctx, execCtx, `{"title":"Note A","content":"Alpha","folder":"/a"}`)
|
|
createTool.Execute(ctx, execCtx, `{"title":"Note B","content":"Beta","folder":"/b"}`)
|
|
|
|
// List all
|
|
listTool := Get("note_list")
|
|
result, err := listTool.Execute(ctx, execCtx, `{}`)
|
|
if err != nil {
|
|
t.Fatalf("Execute: %v", err)
|
|
}
|
|
|
|
var resp map[string]interface{}
|
|
json.Unmarshal([]byte(result), &resp)
|
|
|
|
count := resp["count"].(float64)
|
|
if count != 2 {
|
|
t.Errorf("Expected count=2, got %.0f", count)
|
|
}
|
|
|
|
// List filtered by folder
|
|
result, err = listTool.Execute(ctx, execCtx, `{"folder":"/a"}`)
|
|
if err != nil {
|
|
t.Fatalf("Execute with folder: %v", err)
|
|
}
|
|
json.Unmarshal([]byte(result), &resp)
|
|
count = resp["count"].(float64)
|
|
if count != 1 {
|
|
t.Errorf("Expected count=1 for folder /a, got %.0f", count)
|
|
}
|
|
}
|
|
|
|
func TestNoteSearchExecute(t *testing.T) {
|
|
database.RequireTestDB(t)
|
|
database.TruncateAll(t)
|
|
|
|
userID := database.SeedTestUser(t, "searchuser", "search@test.com")
|
|
channelID := database.SeedTestChannel(t, userID, "Search Test")
|
|
|
|
ctx := context.Background()
|
|
execCtx := ExecutionContext{UserID: userID, ChannelID: channelID}
|
|
|
|
createTool := Get("note_create")
|
|
createTool.Execute(ctx, execCtx, `{"title":"Kubernetes Guide","content":"How to deploy pods and services"}`)
|
|
createTool.Execute(ctx, execCtx, `{"title":"Cooking Tips","content":"Season your cast iron pan properly"}`)
|
|
|
|
searchTool := Get("note_search")
|
|
result, err := searchTool.Execute(ctx, execCtx, `{"query":"kubernetes pods"}`)
|
|
if err != nil {
|
|
t.Fatalf("Execute: %v", err)
|
|
}
|
|
|
|
var resp map[string]interface{}
|
|
json.Unmarshal([]byte(result), &resp)
|
|
count := resp["count"].(float64)
|
|
if count != 1 {
|
|
t.Errorf("Expected 1 search result for 'kubernetes pods', got %.0f", count)
|
|
}
|
|
}
|
|
|
|
func TestNoteUpdateExecute(t *testing.T) {
|
|
database.RequireTestDB(t)
|
|
database.TruncateAll(t)
|
|
|
|
userID := database.SeedTestUser(t, "updateuser", "update@test.com")
|
|
channelID := database.SeedTestChannel(t, userID, "Update Test")
|
|
|
|
ctx := context.Background()
|
|
execCtx := ExecutionContext{UserID: userID, ChannelID: channelID}
|
|
|
|
// Create a note
|
|
createTool := Get("note_create")
|
|
result, _ := createTool.Execute(ctx, execCtx, `{"title":"Original","content":"Original content"}`)
|
|
|
|
var created map[string]interface{}
|
|
json.Unmarshal([]byte(result), &created)
|
|
noteID := created["id"].(string)
|
|
|
|
// Update title
|
|
updateTool := Get("note_update")
|
|
result, err := updateTool.Execute(ctx, execCtx, `{"note_id":"`+noteID+`","title":"Renamed"}`)
|
|
if err != nil {
|
|
t.Fatalf("Update title: %v", err)
|
|
}
|
|
|
|
var updated map[string]interface{}
|
|
json.Unmarshal([]byte(result), &updated)
|
|
if updated["title"] != "Renamed" {
|
|
t.Errorf("Expected title='Renamed', got %v", updated["title"])
|
|
}
|
|
|
|
// Append content
|
|
result, err = updateTool.Execute(ctx, execCtx, `{"note_id":"`+noteID+`","content":"\nNew line","mode":"append"}`)
|
|
if err != nil {
|
|
t.Fatalf("Append: %v", err)
|
|
}
|
|
|
|
// Verify via direct DB read
|
|
var row string
|
|
database.DB.QueryRow("SELECT content FROM notes WHERE id = $1", noteID).Scan(&row)
|
|
if row != "Original content\nNew line" {
|
|
t.Errorf("Append: expected concatenated content, got %q", row)
|
|
}
|
|
}
|
|
|
|
func TestNoteCreateMissingRequiredField(t *testing.T) {
|
|
database.RequireTestDB(t)
|
|
|
|
ctx := context.Background()
|
|
execCtx := ExecutionContext{UserID: "test", ChannelID: "test"}
|
|
|
|
tool := Get("note_create")
|
|
// Missing content
|
|
result, err := tool.Execute(ctx, execCtx, `{"title":"No Content"}`)
|
|
if err == nil {
|
|
// Tools return errors in content, not as Go errors
|
|
var resp map[string]interface{}
|
|
json.Unmarshal([]byte(result), &resp)
|
|
if resp["error"] == nil {
|
|
t.Error("Expected error for missing content")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestNoteUpdateNonexistent(t *testing.T) {
|
|
database.RequireTestDB(t)
|
|
database.TruncateAll(t)
|
|
|
|
userID := database.SeedTestUser(t, "ghostuser", "ghost@test.com")
|
|
|
|
ctx := context.Background()
|
|
execCtx := ExecutionContext{UserID: userID, ChannelID: "test"}
|
|
|
|
tool := Get("note_update")
|
|
_, err := tool.Execute(ctx, execCtx, `{"note_id":"00000000-0000-0000-0000-000000000000","title":"Nope"}`)
|
|
if err == nil {
|
|
t.Log("Update of nonexistent note should return error or empty result")
|
|
}
|
|
}
|