536 lines
13 KiB
Go
536 lines
13 KiB
Go
package collect
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"geo/internal/collect"
|
||
"geo/internal/config"
|
||
"log"
|
||
"os"
|
||
"strings"
|
||
"testing"
|
||
|
||
"github.com/go-rod/rod/lib/proto"
|
||
)
|
||
|
||
var (
|
||
cfg, _ = config.LoadConfig()
|
||
logger = log.New(os.Stdout, "", log.LstdFlags)
|
||
manager = collect.NewCollectManager(context.Background(), cfg, logger)
|
||
)
|
||
|
||
// TestCollectManager_Basic 测试收集管理器的基本功能
|
||
func TestCollectManager_Basic(t *testing.T) {
|
||
|
||
// 测试列出平台
|
||
platforms := manager.ListPlatforms()
|
||
t.Logf("支持的平台: %v", platforms)
|
||
|
||
if len(platforms) != 4 {
|
||
t.Errorf("期望4个平台,实际: %d", len(platforms))
|
||
}
|
||
// 测试获取收集器
|
||
for _, platform := range platforms {
|
||
params := &collect.CollectParams{
|
||
Headless: true,
|
||
UserIndex: "test_user",
|
||
PlatIndex: platform,
|
||
RequestID: "test_req",
|
||
Platform: platform,
|
||
}
|
||
|
||
collector, err := manager.GetCollector(platform, params)
|
||
if err != nil {
|
||
t.Errorf("获取%s收集器失败: %v", platform, err)
|
||
continue
|
||
}
|
||
|
||
if collector == nil {
|
||
t.Errorf("%s收集器为nil", platform)
|
||
}
|
||
|
||
t.Logf("成功创建%s收集器", platform)
|
||
}
|
||
}
|
||
|
||
// TestWenxinCollector_WaitLogin 测试文心一言登录功能
|
||
func TestWenxinCollector_WaitLogin(t *testing.T) {
|
||
if testing.Short() {
|
||
t.Skip("跳过需要浏览器交互的测试")
|
||
}
|
||
|
||
params := &collect.CollectParams{
|
||
Headless: false, // 显示浏览器窗口以便扫码登录
|
||
UserIndex: "test_user",
|
||
PlatIndex: "wenxin",
|
||
RequestID: "test_wenxin_login_001",
|
||
Platform: "wenxin",
|
||
}
|
||
|
||
t.Log("开始测试文心一言登录...")
|
||
t.Log("请在打开的浏览器窗口中完成百度账号登录(扫码或输入账号密码)")
|
||
|
||
success, msg := manager.WaitLogin("wenxin", params)
|
||
|
||
if !success {
|
||
t.Errorf("文心一言登录失败: %s", msg)
|
||
return
|
||
}
|
||
|
||
t.Logf("文心一言登录成功: %s", msg)
|
||
t.Log("Cookie已保存,后续测试可以使用已登录状态")
|
||
}
|
||
|
||
// TestWenxinCollector_SimpleAsk 简单测试文心一言提问
|
||
func TestWenxinCollector_SimpleAsk(t *testing.T) {
|
||
if testing.Short() {
|
||
t.Skip("跳过需要浏览器交互的测试")
|
||
}
|
||
|
||
params := &collect.CollectParams{
|
||
Headless: false, // 显示浏览器以便观察
|
||
UserIndex: "test_user",
|
||
PlatIndex: "wenxin",
|
||
RequestID: "test_wenxin_simple_001",
|
||
Platform: "wenxin",
|
||
}
|
||
|
||
t.Log("=== 简单测试文心一言提问 ===")
|
||
|
||
// 获取收集器
|
||
collector, err := manager.GetCollector("wenxin", params)
|
||
if err != nil {
|
||
t.Fatalf("获取收集器失败: %v", err)
|
||
}
|
||
|
||
wenxinCollector := collector.(*collect.WenxinCollector)
|
||
|
||
// 初始化浏览器
|
||
if err := wenxinCollector.SetupDriver(); err != nil {
|
||
t.Fatalf("启动浏览器失败: %v", err)
|
||
}
|
||
defer wenxinCollector.Close()
|
||
|
||
// 加载Cookie
|
||
if err := wenxinCollector.LoadCookies(); err != nil {
|
||
t.Logf("未找到Cookie文件: %v", err)
|
||
}
|
||
|
||
// 导航到聊天页面
|
||
wenxinCollector.Page.MustNavigate(wenxinCollector.ChatURL)
|
||
wenxinCollector.Sleep(5)
|
||
|
||
// 检查登录状态
|
||
isLoggedIn := wenxinCollector.CheckLoginStatus()
|
||
t.Logf("登录状态: %v", isLoggedIn)
|
||
|
||
if !isLoggedIn {
|
||
t.Fatal("未登录,请先调用WaitLogin登录")
|
||
}
|
||
|
||
// 手动输入问题
|
||
question := "你好"
|
||
t.Logf("准备输入问题: %s", question)
|
||
|
||
// 查找输入框
|
||
inputBox, err := wenxinCollector.WaitForElementVisible("[contenteditable='true']", 10)
|
||
if err != nil {
|
||
t.Fatalf("未找到输入框: %v", err)
|
||
}
|
||
t.Log("✓ 找到输入框")
|
||
|
||
// 点击输入框
|
||
inputBox.Click(proto.InputMouseButtonLeft, 1)
|
||
wenxinCollector.SleepMs(500)
|
||
|
||
// 清空输入框
|
||
wenxinCollector.ClearInput(inputBox)
|
||
wenxinCollector.SleepMs(300)
|
||
|
||
// 使用键盘输入
|
||
t.Log("正在输入问题...")
|
||
inputBox.Input(question)
|
||
wenxinCollector.SleepMs(1000)
|
||
t.Log("✓ 问题已输入")
|
||
|
||
// 查找并点击发送按钮
|
||
sendBtn, err := wenxinCollector.Page.Element("button")
|
||
if err != nil {
|
||
t.Fatalf("未找到发送按钮: %v", err)
|
||
}
|
||
t.Log("✓ 找到发送按钮")
|
||
|
||
t.Log("正在点击发送按钮...")
|
||
sendBtn.Click(proto.InputMouseButtonLeft, 1)
|
||
wenxinCollector.SleepMs(3000)
|
||
t.Log("✓ 已点击发送按钮")
|
||
|
||
t.Log("\n请观察浏览器窗口,查看是否成功发送问题并收到回答")
|
||
t.Log("测试将在10秒后结束...")
|
||
wenxinCollector.Sleep(10)
|
||
|
||
t.Log("=== 测试完成 ===")
|
||
}
|
||
|
||
// TestWenxinCollector_AskQuestion 测试文心一言提问功能
|
||
// 注意:此测试需要有效的登录状态
|
||
func TestWenxinCollector_AskQuestion(t *testing.T) {
|
||
if testing.Short() {
|
||
t.Skip("跳过需要浏览器交互的测试")
|
||
}
|
||
|
||
// 设置收集参数
|
||
params := &collect.CollectParams{
|
||
Headless: false, // 显示浏览器以便调试
|
||
UserIndex: "test_user",
|
||
PlatIndex: "wenxin",
|
||
RequestID: "test_wenxin_001",
|
||
Platform: "wenxin",
|
||
}
|
||
|
||
// 定义提问内容
|
||
question := "请用一句话介绍Go语言"
|
||
t.Logf("向文心一言提问: %s", question)
|
||
|
||
// 调用管理器提问并获取答案
|
||
answer, err := manager.AskQuestion("wenxin", params, question)
|
||
if err != nil {
|
||
t.Errorf("提问失败: %v", err)
|
||
return
|
||
}
|
||
|
||
t.Logf("获取到答案:\n%s", answer)
|
||
|
||
// 验证答案非空
|
||
if len(answer) == 0 {
|
||
t.Error("答案为空")
|
||
}
|
||
}
|
||
|
||
// TestMultiplePlatforms_Compare 测试多平台对比
|
||
func TestMultiplePlatforms_Compare(t *testing.T) {
|
||
if testing.Short() {
|
||
t.Skip("跳过需要浏览器交互的测试")
|
||
}
|
||
|
||
question := "什么是人工智能?"
|
||
platforms := []string{"wenxin", "deepseek"}
|
||
|
||
results := make(map[string]string)
|
||
|
||
for _, platform := range platforms {
|
||
params := &collect.CollectParams{
|
||
Headless: true,
|
||
UserIndex: "test_user",
|
||
PlatIndex: platform,
|
||
RequestID: fmt.Sprintf("test_%s", platform),
|
||
Platform: platform,
|
||
}
|
||
|
||
t.Logf("正在向%s提问...", platform)
|
||
answer, err := manager.AskQuestion(platform, params, question)
|
||
if err != nil {
|
||
t.Logf("%s提问失败: %v", platform, err)
|
||
results[platform] = fmt.Sprintf("错误: %v", err)
|
||
continue
|
||
}
|
||
|
||
results[platform] = answer
|
||
t.Logf("%s回答完成,长度: %d", platform, len(answer))
|
||
}
|
||
|
||
// 输出对比结果
|
||
t.Log("\n===== 多平台回答对比 =====")
|
||
for platform, answer := range results {
|
||
t.Logf("\n[%s]:\n%s\n", platform, answer)
|
||
}
|
||
}
|
||
|
||
// TestWenxinCollector_DebugPageStructure 调试页面结构
|
||
func TestWenxinCollector_DebugPageStructure(t *testing.T) {
|
||
if testing.Short() {
|
||
t.Skip("跳过需要浏览器交互的测试")
|
||
}
|
||
|
||
params := &collect.CollectParams{
|
||
Headless: false,
|
||
UserIndex: "test_user",
|
||
PlatIndex: "wenxin",
|
||
RequestID: "test_wenxin_debug_001",
|
||
Platform: "wenxin",
|
||
}
|
||
|
||
t.Log("=== 调试文心一言页面结构 ===")
|
||
|
||
// 获取收集器
|
||
collector, err := manager.GetCollector("wenxin", params)
|
||
if err != nil {
|
||
t.Fatalf("获取收集器失败: %v", err)
|
||
}
|
||
|
||
wenxinCollector := collector.(*collect.WenxinCollector)
|
||
if err := wenxinCollector.SetupDriver(); err != nil {
|
||
t.Fatalf("启动浏览器失败: %v", err)
|
||
}
|
||
defer wenxinCollector.Close()
|
||
|
||
// 加载Cookie
|
||
if err := wenxinCollector.LoadCookies(); err != nil {
|
||
t.Logf("未找到Cookie文件: %v", err)
|
||
}
|
||
|
||
// 导航到聊天页面
|
||
wenxinCollector.Page.MustNavigate(wenxinCollector.ChatURL)
|
||
wenxinCollector.Sleep(5)
|
||
|
||
// 检查登录状态
|
||
isLoggedIn := wenxinCollector.CheckLoginStatus()
|
||
t.Logf("登录状态: %v", isLoggedIn)
|
||
|
||
if !isLoggedIn {
|
||
t.Fatal("未登录,请先调用WaitLogin登录")
|
||
}
|
||
|
||
// 查找所有可能的输入框
|
||
t.Log("\n=== 查找输入框 ===")
|
||
inputSelectors := []string{
|
||
"textarea",
|
||
"[contenteditable='true']",
|
||
"input[type='text']",
|
||
".input-box",
|
||
"#chat-input",
|
||
"[placeholder]",
|
||
}
|
||
|
||
for _, selector := range inputSelectors {
|
||
elements, err := wenxinCollector.Page.Elements(selector)
|
||
if err == nil && len(elements) > 0 {
|
||
t.Logf("✓ 找到 %d 个元素: %s", len(elements), selector)
|
||
for i, elem := range elements {
|
||
if i >= 3 {
|
||
break // 只显示前3个
|
||
}
|
||
text, _ := elem.Text()
|
||
tagName, _ := elem.Property("tagName")
|
||
class, _ := elem.Attribute("class")
|
||
id, _ := elem.Attribute("id")
|
||
placeholder, _ := elem.Attribute("placeholder")
|
||
|
||
idStr := ""
|
||
if id != nil {
|
||
idStr = *id
|
||
}
|
||
classStr := ""
|
||
if class != nil {
|
||
classStr = *class
|
||
}
|
||
placeholderStr := ""
|
||
if placeholder != nil {
|
||
placeholderStr = *placeholder
|
||
}
|
||
|
||
t.Logf(" [%d] tag=%s, id=%s, class=%s, placeholder=%s, text=%s",
|
||
i, tagName.Str(), idStr, classStr, placeholderStr, text[:min(50, len(text))])
|
||
}
|
||
} else {
|
||
t.Logf("✗ 未找到元素: %s", selector)
|
||
}
|
||
}
|
||
|
||
// 查找所有按钮
|
||
t.Log("\n=== 查找发送按钮 ===")
|
||
buttonSelectors := []string{
|
||
"button",
|
||
"svg",
|
||
"[aria-label]",
|
||
}
|
||
|
||
for _, selector := range buttonSelectors {
|
||
elements, err := wenxinCollector.Page.Elements(selector)
|
||
if err == nil && len(elements) > 0 {
|
||
t.Logf("✓ 找到 %d 个元素: %s", len(elements), selector)
|
||
for i, elem := range elements {
|
||
if i >= 5 {
|
||
break
|
||
}
|
||
text, _ := elem.Text()
|
||
tagName, _ := elem.Property("tagName")
|
||
class, _ := elem.Attribute("class")
|
||
ariaLabel, _ := elem.Attribute("aria-label")
|
||
ariaLabelText := ""
|
||
if ariaLabel != nil {
|
||
ariaLabelText = *ariaLabel
|
||
}
|
||
|
||
classStr := ""
|
||
if class != nil {
|
||
classStr = *class
|
||
}
|
||
|
||
trimmedText := strings.TrimSpace(text)
|
||
if trimmedText != "" || ariaLabelText != "" {
|
||
t.Logf(" [%d] tag=%s, class=%s, aria-label=%s, text=%s",
|
||
i, tagName.Str(), classStr, ariaLabelText, trimmedText[:min(30, len(trimmedText))])
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
t.Log("\n=== 调试完成 ===")
|
||
t.Log("请保持浏览器窗口打开,手动检查页面结构")
|
||
|
||
// 等待用户观察
|
||
select {}
|
||
}
|
||
|
||
// TestWenxinCollector_DebugAnswer 调试答案区域
|
||
func TestWenxinCollector_DebugAnswer(t *testing.T) {
|
||
if testing.Short() {
|
||
t.Skip("跳过需要浏览器交互的测试")
|
||
}
|
||
|
||
params := &collect.CollectParams{
|
||
Headless: false,
|
||
UserIndex: "test_user",
|
||
PlatIndex: "wenxin",
|
||
RequestID: "test_wenxin_debug_answer",
|
||
Platform: "wenxin",
|
||
}
|
||
|
||
t.Log("=== 调试文心一言答案区域 ===")
|
||
|
||
collector, err := manager.GetCollector("wenxin", params)
|
||
if err != nil {
|
||
t.Fatalf("获取收集器失败: %v", err)
|
||
}
|
||
|
||
wenxinCollector := collector.(*collect.WenxinCollector)
|
||
if err := wenxinCollector.SetupDriver(); err != nil {
|
||
t.Fatalf("启动浏览器失败: %v", err)
|
||
}
|
||
defer wenxinCollector.Close()
|
||
|
||
if err := wenxinCollector.LoadCookies(); err != nil {
|
||
t.Logf("未找到Cookie文件: %v", err)
|
||
}
|
||
|
||
wenxinCollector.Page.MustNavigate(wenxinCollector.ChatURL)
|
||
wenxinCollector.Sleep(5)
|
||
|
||
if !wenxinCollector.CheckLoginStatus() {
|
||
t.Fatal("未登录")
|
||
}
|
||
|
||
// 手动输入问题并发送
|
||
t.Log("请在浏览器中手动输入问题并等待AI回答完成")
|
||
t.Log("然后按回车键继续...")
|
||
fmt.Scanln()
|
||
|
||
// 查找所有可能的答案容器
|
||
t.Log("\n=== 查找答案容器 ===")
|
||
|
||
// 方式1: 查找包含answer/response/message的元素
|
||
containers, _ := wenxinCollector.Page.Elements("[class*='answer'], [class*='response'], [class*='message']")
|
||
t.Logf("找到 %d 个容器元素", len(containers))
|
||
for i, container := range containers {
|
||
text, _ := container.Text()
|
||
classAttr, _ := container.Attribute("class")
|
||
tagName, _ := container.Property("tagName")
|
||
|
||
classStr := ""
|
||
if classAttr != nil {
|
||
classStr = *classAttr
|
||
}
|
||
|
||
if len(strings.TrimSpace(text)) > 20 {
|
||
t.Logf("[%d] tag=%s, class=%s, text长度=%d, 前100字符=%s",
|
||
i, tagName.Str(), classStr, len(text), text[:min(100, len(text))])
|
||
}
|
||
}
|
||
|
||
// 方式2: 查找所有div,显示较长的文本
|
||
t.Log("\n=== 查找长文本div ===")
|
||
allDivs, _ := wenxinCollector.Page.Elements("div")
|
||
var longTextDivs []struct{
|
||
index int
|
||
text string
|
||
class string
|
||
}
|
||
|
||
for i, div := range allDivs {
|
||
text, _ := div.Text()
|
||
if len(strings.TrimSpace(text)) > 50 {
|
||
classAttr, _ := div.Attribute("class")
|
||
classStr := ""
|
||
if classAttr != nil {
|
||
classStr = *classAttr
|
||
}
|
||
longTextDivs = append(longTextDivs, struct{
|
||
index int
|
||
text string
|
||
class string
|
||
}{i, text, classStr})
|
||
}
|
||
}
|
||
|
||
t.Logf("找到 %d 个长文本div", len(longTextDivs))
|
||
for _, item := range longTextDivs {
|
||
t.Logf("[%d] class=%s, 长度=%d, 前150字符=%s",
|
||
item.index, item.class, len(item.text), item.text[:min(150, len(item.text))])
|
||
}
|
||
|
||
t.Log("\n=== 调试完成,请保持浏览器打开以便观察 ===")
|
||
select {}
|
||
}
|
||
|
||
// BenchmarkWenxinCollector 性能测试(仅供参考)
|
||
func BenchmarkWenxinCollector(b *testing.B) {
|
||
b.Skip("跳过性能测试")
|
||
}
|
||
|
||
// ExampleCollectManager 使用示例
|
||
func ExampleCollectManager() {
|
||
|
||
// 列出支持的平台
|
||
platforms := manager.ListPlatforms()
|
||
fmt.Printf("支持的平台: %v\n", platforms)
|
||
|
||
// 设置参数
|
||
params := &collect.CollectParams{
|
||
Headless: true,
|
||
UserIndex: "user_001",
|
||
PlatIndex: "wenxin",
|
||
RequestID: "req_001",
|
||
Platform: "wenxin",
|
||
}
|
||
|
||
// 向文心一言提问
|
||
answer, err := manager.AskQuestion("wenxin", params, "什么是人工智能?")
|
||
if err != nil {
|
||
fmt.Printf("错误: %v\n", err)
|
||
return
|
||
}
|
||
|
||
fmt.Printf("答案: %s\n", answer)
|
||
}
|
||
|
||
// ExampleWenxinCollector_WaitLogin 文心一言登录示例
|
||
func ExampleWenxinCollector_WaitLogin() {
|
||
params := &collect.CollectParams{
|
||
Headless: false, // 登录时需要显示浏览器
|
||
UserIndex: "user_001",
|
||
PlatIndex: "wenxin",
|
||
RequestID: "example_login_001",
|
||
Platform: "wenxin",
|
||
}
|
||
|
||
fmt.Println("正在打开文心一言登录页面...")
|
||
success, msg := manager.WaitLogin("wenxin", params)
|
||
if success {
|
||
fmt.Printf("登录成功: %s\n", msg)
|
||
fmt.Println("Cookie已保存,下次可以自动登录")
|
||
} else {
|
||
fmt.Printf("登录失败: %s\n", msg)
|
||
}
|
||
}
|