package repository import ( "context" "encoding/json" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gorm.io/gorm" "github.com/gochat/gochat/internal/model" ) // helper: create a test account and return its ID func createCustomToolTestAccount(t *testing.T, db *gorm.DB) uint { t.Helper() acct := &model.Account{Name: "CustomToolTestOrg", Locale: "en", Active: true} require.NoError(t, db.Create(acct).Error) return acct.ID } // helper: build a minimal valid CaptainCustomTool func newTestCustomTool(accountID uint, slug string) *model.CaptainCustomTool { return &model.CaptainCustomTool{ AccountID: accountID, Title: "测试工具-" + slug, Slug: slug, Description: "用于测试的自定义工具", EndpointURL: "https://api.example.com/v1/" + slug, HTTPMethod: "POST", AuthType: model.ToolAuthTypeNone, AuthConfig: json.RawMessage(`{"type":"none"}`), ParamSchema: json.RawMessage(`{"type":"object","properties":{"query":{"type":"string"}}}`), Enabled: true, } } // ========== Create ========== func TestCaptainCustomToolRepo_Create(t *testing.T) { db := setupTestDB(t, &model.CaptainCustomTool{}) repo := NewCaptainCustomToolRepo(db) accountID := createCustomToolTestAccount(t, db) tool := newTestCustomTool(accountID, "create-tool") err := repo.Create(context.Background(), tool) require.NoError(t, err) assert.NotZero(t, tool.ID) assert.Equal(t, accountID, tool.AccountID) assert.Equal(t, "create-tool", tool.Slug) assert.Equal(t, "POST", tool.HTTPMethod) assert.Equal(t, model.ToolAuthTypeNone, tool.AuthType) assert.True(t, tool.Enabled) } func TestCaptainCustomToolRepo_Create_WithBearerAuth(t *testing.T) { db := setupTestDB(t, &model.CaptainCustomTool{}) repo := NewCaptainCustomToolRepo(db) accountID := createCustomToolTestAccount(t, db) tool := newTestCustomTool(accountID, "bearer-tool") tool.AuthType = model.ToolAuthTypeBearer tool.AuthConfig = json.RawMessage(`{"token":"secret-bearer-token"}`) err := repo.Create(context.Background(), tool) require.NoError(t, err) assert.NotZero(t, tool.ID) assert.Equal(t, model.ToolAuthTypeBearer, tool.AuthType) // Verify auth_config persisted correctly found, err := repo.GetByID(context.Background(), tool.ID) require.NoError(t, err) assert.Equal(t, tool.AuthConfig, found.AuthConfig) } // ========== GetByID ========== func TestCaptainCustomToolRepo_GetByID(t *testing.T) { db := setupTestDB(t, &model.CaptainCustomTool{}) repo := NewCaptainCustomToolRepo(db) accountID := createCustomToolTestAccount(t, db) tool := newTestCustomTool(accountID, "getbyid-tool") require.NoError(t, repo.Create(context.Background(), tool)) found, err := repo.GetByID(context.Background(), tool.ID) require.NoError(t, err) assert.Equal(t, tool.ID, found.ID) assert.Equal(t, tool.Title, found.Title) assert.Equal(t, tool.Slug, found.Slug) assert.Equal(t, tool.EndpointURL, found.EndpointURL) assert.Equal(t, tool.ParamSchema, found.ParamSchema) } func TestCaptainCustomToolRepo_GetByID_NotFound(t *testing.T) { db := setupTestDB(t, &model.CaptainCustomTool{}) repo := NewCaptainCustomToolRepo(db) found, err := repo.GetByID(context.Background(), 99999) assert.Error(t, err) assert.Nil(t, found) } // ========== GetBySlug ========== func TestCaptainCustomToolRepo_GetBySlug(t *testing.T) { db := setupTestDB(t, &model.CaptainCustomTool{}) repo := NewCaptainCustomToolRepo(db) accountID := createCustomToolTestAccount(t, db) tool := newTestCustomTool(accountID, "slug-tool") require.NoError(t, repo.Create(context.Background(), tool)) found, err := repo.GetBySlug(context.Background(), accountID, "slug-tool") require.NoError(t, err) assert.Equal(t, tool.ID, found.ID) assert.Equal(t, "slug-tool", found.Slug) assert.Equal(t, accountID, found.AccountID) } func TestCaptainCustomToolRepo_GetBySlug_NotFound(t *testing.T) { db := setupTestDB(t, &model.CaptainCustomTool{}) repo := NewCaptainCustomToolRepo(db) accountID := createCustomToolTestAccount(t, db) found, err := repo.GetBySlug(context.Background(), accountID, "nonexistent-slug") assert.Error(t, err) assert.Nil(t, found) } // ========== Update ========== func TestCaptainCustomToolRepo_Update(t *testing.T) { db := setupTestDB(t, &model.CaptainCustomTool{}) repo := NewCaptainCustomToolRepo(db) accountID := createCustomToolTestAccount(t, db) tool := newTestCustomTool(accountID, "update-tool") require.NoError(t, repo.Create(context.Background(), tool)) // Modify fields tool.Title = "更新后的工具" tool.Description = "更新描述" tool.EndpointURL = "https://api.newendpoint.com/v2" tool.HTTPMethod = "GET" tool.AuthType = model.ToolAuthTypeBasic tool.AuthConfig = json.RawMessage(`{"username":"admin","password":"pass123"}`) tool.Enabled = false err := repo.Update(context.Background(), tool) require.NoError(t, err) found, err := repo.GetByID(context.Background(), tool.ID) require.NoError(t, err) assert.Equal(t, "更新后的工具", found.Title) assert.Equal(t, "更新描述", found.Description) assert.Equal(t, "https://api.newendpoint.com/v2", found.EndpointURL) assert.Equal(t, "GET", found.HTTPMethod) assert.Equal(t, model.ToolAuthTypeBasic, found.AuthType) assert.False(t, found.Enabled) } // ========== Delete ========== func TestCaptainCustomToolRepo_Delete(t *testing.T) { db := setupTestDB(t, &model.CaptainCustomTool{}) repo := NewCaptainCustomToolRepo(db) accountID := createCustomToolTestAccount(t, db) tool := newTestCustomTool(accountID, "delete-tool") require.NoError(t, repo.Create(context.Background(), tool)) err := repo.Delete(context.Background(), tool.ID) require.NoError(t, err) // Verify it's gone found, err := repo.GetByID(context.Background(), tool.ID) assert.Error(t, err) assert.Nil(t, found) } func TestCaptainCustomToolRepo_Delete_NotFound(t *testing.T) { db := setupTestDB(t, &model.CaptainCustomTool{}) repo := NewCaptainCustomToolRepo(db) // Deleting a non-existent ID should not error (GORM returns nil for zero rows) err := repo.Delete(context.Background(), 99999) assert.NoError(t, err) } // ========== ListByAccount ========== func TestCaptainCustomToolRepo_ListByAccount(t *testing.T) { db := setupTestDB(t, &model.CaptainCustomTool{}) repo := NewCaptainCustomToolRepo(db) accountID := createCustomToolTestAccount(t, db) // Create 3 tools for the same account for i, slug := range []string{"list-a", "list-b", "list-c"} { tool := newTestCustomTool(accountID, slug) tool.Title = "列表工具" + string(rune('A' + i)) require.NoError(t, repo.Create(context.Background(), tool)) } // List with offset=0, limit=2 tools, count, err := repo.ListByAccount(context.Background(), accountID, 0, 2) require.NoError(t, err) assert.Equal(t, int64(3), count) assert.Len(t, tools, 2) // List with offset=2, limit=10 (should return 1 remaining) tools2, count2, err := repo.ListByAccount(context.Background(), accountID, 2, 10) require.NoError(t, err) assert.Equal(t, int64(3), count2) assert.Len(t, tools2, 1) } func TestCaptainCustomToolRepo_ListByAccount_Empty(t *testing.T) { db := setupTestDB(t, &model.CaptainCustomTool{}) repo := NewCaptainCustomToolRepo(db) accountID := createCustomToolTestAccount(t, db) tools, count, err := repo.ListByAccount(context.Background(), accountID, 0, 10) require.NoError(t, err) assert.Equal(t, int64(0), count) assert.Empty(t, tools) } // ========== CountByAccount ========== func TestCaptainCustomToolRepo_CountByAccount(t *testing.T) { db := setupTestDB(t, &model.CaptainCustomTool{}) repo := NewCaptainCustomToolRepo(db) accountID := createCustomToolTestAccount(t, db) // Initially 0 cnt, err := repo.CountByAccount(context.Background(), accountID) require.NoError(t, err) assert.Equal(t, int64(0), cnt) // Create 2 tools require.NoError(t, repo.Create(context.Background(), newTestCustomTool(accountID, "count-a"))) require.NoError(t, repo.Create(context.Background(), newTestCustomTool(accountID, "count-b"))) cnt, err = repo.CountByAccount(context.Background(), accountID) require.NoError(t, err) assert.Equal(t, int64(2), cnt) }