- Reorganized import statements in test files to improve clarity and consistency. - Updated comments in test cases to provide more detailed descriptions of the test environment initialization process. - Enhanced the `Prepare` function in the test utilities to include registration of the default query engine, ensuring proper setup for database searches. - Improved error handling during the loading of the knowledge base and query engine, enhancing robustness in test setups.
191 lines
5 KiB
Go
191 lines
5 KiB
Go
package search_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/yaoapp/gou/model"
|
|
"github.com/yaoapp/yao/agent/context"
|
|
"github.com/yaoapp/yao/agent/search"
|
|
"github.com/yaoapp/yao/agent/search/types"
|
|
"github.com/yaoapp/yao/agent/testutils"
|
|
oauthTypes "github.com/yaoapp/yao/openapi/oauth/types"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// ============================================================================
|
|
// DB Search JSAPI Integration Tests
|
|
// ============================================================================
|
|
|
|
func TestJSAPI_DB_Integration(t *testing.T) {
|
|
// Skip if running short tests
|
|
if testing.Short() {
|
|
t.Skip("Skipping integration test")
|
|
}
|
|
|
|
// Initialize test environment (loads models, database, query engine, etc.)
|
|
testutils.Prepare(t)
|
|
defer testutils.Clean(t)
|
|
|
|
// Create test context
|
|
ctx := newJSAPITestContext(t)
|
|
|
|
// Verify __yao.role model is loaded
|
|
mod := model.Select("__yao.role")
|
|
require.NotNil(t, mod, "__yao.role model should be loaded")
|
|
|
|
// Ensure test data exists
|
|
ensureJSAPITestRole(t, mod)
|
|
|
|
t.Run("db_search_with_context", func(t *testing.T) {
|
|
api := search.NewJSAPI(ctx, &types.Config{
|
|
DB: &types.DBConfig{
|
|
Models: []string{"__yao.role"},
|
|
MaxResults: 10,
|
|
},
|
|
}, &search.Uses{QueryDSL: "builtin"})
|
|
|
|
result := api.DB("查询所有角色", map[string]interface{}{
|
|
"models": []interface{}{"__yao.role"},
|
|
"limit": float64(10),
|
|
})
|
|
|
|
require.NotNil(t, result)
|
|
r, ok := result.(*types.Result)
|
|
require.True(t, ok)
|
|
|
|
assert.Equal(t, types.SearchTypeDB, r.Type)
|
|
assert.Equal(t, "查询所有角色", r.Query)
|
|
assert.Equal(t, types.SourceHook, r.Source)
|
|
|
|
if r.Error != "" {
|
|
t.Logf("Search error: %s", r.Error)
|
|
}
|
|
assert.Empty(t, r.Error, "Should not have error")
|
|
assert.Greater(t, len(r.Items), 0, "Should have results")
|
|
})
|
|
|
|
t.Run("db_search_with_scenario", func(t *testing.T) {
|
|
api := search.NewJSAPI(ctx, &types.Config{
|
|
DB: &types.DBConfig{
|
|
Models: []string{"__yao.role"},
|
|
MaxResults: 5,
|
|
},
|
|
}, &search.Uses{QueryDSL: "builtin"})
|
|
|
|
result := api.DB("查询系统角色", map[string]interface{}{
|
|
"models": []interface{}{"__yao.role"},
|
|
"scenario": "filter",
|
|
"limit": float64(5),
|
|
})
|
|
|
|
require.NotNil(t, result)
|
|
r, ok := result.(*types.Result)
|
|
require.True(t, ok)
|
|
|
|
assert.Equal(t, types.SearchTypeDB, r.Type)
|
|
assert.LessOrEqual(t, len(r.Items), 5, "Should respect limit")
|
|
})
|
|
|
|
t.Run("db_search_with_select_fields", func(t *testing.T) {
|
|
api := search.NewJSAPI(ctx, &types.Config{
|
|
DB: &types.DBConfig{
|
|
Models: []string{"__yao.role"},
|
|
MaxResults: 10,
|
|
},
|
|
}, &search.Uses{QueryDSL: "builtin"})
|
|
|
|
result := api.DB("查询角色名称", map[string]interface{}{
|
|
"models": []interface{}{"__yao.role"},
|
|
"select": []interface{}{"id", "name", "description"},
|
|
"limit": float64(10),
|
|
})
|
|
|
|
require.NotNil(t, result)
|
|
r, ok := result.(*types.Result)
|
|
require.True(t, ok)
|
|
|
|
assert.Equal(t, types.SearchTypeDB, r.Type)
|
|
if r.Error == "" && len(r.Items) > 0 {
|
|
// Verify items have data
|
|
for _, item := range r.Items {
|
|
assert.NotNil(t, item.Data)
|
|
assert.Equal(t, "__yao.role", item.Model)
|
|
}
|
|
}
|
|
})
|
|
|
|
t.Run("db_search_all_with_multiple_types", func(t *testing.T) {
|
|
api := search.NewJSAPI(ctx, &types.Config{
|
|
KB: &types.KBConfig{Collections: []string{"docs"}},
|
|
DB: &types.DBConfig{
|
|
Models: []string{"__yao.role"},
|
|
MaxResults: 10,
|
|
},
|
|
}, &search.Uses{QueryDSL: "builtin"})
|
|
|
|
requests := []interface{}{
|
|
map[string]interface{}{
|
|
"type": "db",
|
|
"query": "查询角色",
|
|
"models": []interface{}{"__yao.role"},
|
|
"limit": float64(5),
|
|
},
|
|
map[string]interface{}{
|
|
"type": "kb",
|
|
"query": "知识库查询",
|
|
"collections": []interface{}{"docs"},
|
|
"limit": float64(5),
|
|
},
|
|
}
|
|
|
|
results := api.All(requests)
|
|
require.Len(t, results, 2)
|
|
|
|
// DB result
|
|
r0, ok := results[0].(*types.Result)
|
|
require.True(t, ok)
|
|
assert.Equal(t, types.SearchTypeDB, r0.Type)
|
|
|
|
// KB result
|
|
r1, ok := results[1].(*types.Result)
|
|
require.True(t, ok)
|
|
assert.Equal(t, types.SearchTypeKB, r1.Type)
|
|
})
|
|
}
|
|
|
|
// newJSAPITestContext creates a test context for JSAPI tests
|
|
func newJSAPITestContext(t *testing.T) *context.Context {
|
|
t.Helper()
|
|
authorized := &oauthTypes.AuthorizedInfo{
|
|
UserID: "test-user-jsapi",
|
|
}
|
|
chatID := "test-chat-jsapi-db"
|
|
ctx := context.New(t.Context(), authorized, chatID)
|
|
return ctx
|
|
}
|
|
|
|
// ensureJSAPITestRole ensures there's at least one role in the database
|
|
func ensureJSAPITestRole(t *testing.T, mod *model.Model) {
|
|
t.Helper()
|
|
|
|
// Try to find existing roles
|
|
rows, err := mod.Get(model.QueryParam{Limit: 1})
|
|
if err == nil && len(rows) > 0 {
|
|
return
|
|
}
|
|
|
|
// Create a test role
|
|
_, err = mod.Create(map[string]interface{}{
|
|
"role_id": "jsapi_test_role",
|
|
"name": "JSAPI Test Role",
|
|
"description": "A test role for JSAPI unit testing",
|
|
"is_active": true,
|
|
"is_system": false,
|
|
"level": 1,
|
|
})
|
|
if err != nil {
|
|
t.Logf("Note: Could not create test role: %v", err)
|
|
}
|
|
}
|