221 lines
6.3 KiB
Go
221 lines
6.3 KiB
Go
package chat
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"hfb_sys/backend/internal/model"
|
|
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/logger"
|
|
)
|
|
|
|
func setupQrCodeTestDB(t *testing.T) *gorm.DB {
|
|
t.Helper()
|
|
db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{
|
|
Logger: logger.Default.LogMode(logger.Silent),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("无法创建测试数据库: %v", err)
|
|
}
|
|
if err := db.AutoMigrate(&model.ChatQrCode{}, &model.ChatConversation{}, &model.SystemConfig{}); err != nil {
|
|
t.Fatalf("数据库迁移失败: %v", err)
|
|
}
|
|
return db
|
|
}
|
|
|
|
func TestGetQrCodeOCRConfigReadsSystemConfig(t *testing.T) {
|
|
db := setupQrCodeTestDB(t)
|
|
repo := NewRepository(db, nil)
|
|
rows := []model.SystemConfig{
|
|
{Key: qrCodeOCRTokenConfigKey, Value: "test-token"},
|
|
{Key: qrCodeOCRJobURLConfigKey, Value: "https://example.test/ocr/jobs"},
|
|
{Key: qrCodeOCRModelConfigKey, Value: "PaddleOCR-Test"},
|
|
}
|
|
if err := db.Create(&rows).Error; err != nil {
|
|
t.Fatalf("创建系统配置失败: %v", err)
|
|
}
|
|
|
|
config, err := repo.GetQrCodeOCRConfig(t.Context())
|
|
if err != nil {
|
|
t.Fatalf("读取 OCR 配置失败: %v", err)
|
|
}
|
|
if config.Token != "test-token" {
|
|
t.Fatalf("token = %q", config.Token)
|
|
}
|
|
if config.JobURL != "https://example.test/ocr/jobs" {
|
|
t.Fatalf("job_url = %q", config.JobURL)
|
|
}
|
|
if config.Model != "PaddleOCR-Test" {
|
|
t.Fatalf("model = %q", config.Model)
|
|
}
|
|
}
|
|
|
|
func TestListQrCodesIncludesBoundConversationTitle(t *testing.T) {
|
|
db := setupQrCodeTestDB(t)
|
|
repo := NewRepository(db, nil)
|
|
conversation := model.ChatConversation{
|
|
Title: "账号群 L202606180001",
|
|
Type: ConversationTypeListingGroup,
|
|
Status: "active",
|
|
}
|
|
if err := db.Create(&conversation).Error; err != nil {
|
|
t.Fatalf("创建群聊失败: %v", err)
|
|
}
|
|
|
|
qrcode := model.ChatQrCode{
|
|
ImageURL: "/api/files/object?key=qrcode/group.png",
|
|
GroupName: "王大锤-鼠鼠跑刀一群",
|
|
Status: QrCodeStatusUsed,
|
|
ConversationID: &conversation.ID,
|
|
CreatedBy: 1,
|
|
}
|
|
if err := db.Create(&qrcode).Error; err != nil {
|
|
t.Fatalf("创建二维码失败: %v", err)
|
|
}
|
|
|
|
items, total, err := repo.ListQrCodes(t.Context(), QrCodeListRequest{Page: 1, Limit: 20})
|
|
if err != nil {
|
|
t.Fatalf("查询二维码失败: %v", err)
|
|
}
|
|
if total != 1 || len(items) != 1 {
|
|
t.Fatalf("total = %d, len = %d, want 1", total, len(items))
|
|
}
|
|
if items[0].GroupName != "王大锤-鼠鼠跑刀一群" {
|
|
t.Fatalf("群名 = %q", items[0].GroupName)
|
|
}
|
|
if items[0].BoundConversationTitle != "账号群 L202606180001" {
|
|
t.Fatalf("绑定群名 = %q", items[0].BoundConversationTitle)
|
|
}
|
|
}
|
|
|
|
func TestParseQrCodeGroupNameCandidates(t *testing.T) {
|
|
rawText := strings.Join([]string{
|
|
"使用微信或企业微信扫码加入",
|
|
"王大锤-鼠鼠跑刀一群",
|
|
"这二维码7天内有效",
|
|
}, "\n")
|
|
|
|
candidates := parseQrCodeGroupNameCandidates(rawText)
|
|
if len(candidates) == 0 {
|
|
t.Fatal("未解析出群名候选")
|
|
}
|
|
if candidates[0] != "王大锤-鼠鼠跑刀一群" {
|
|
t.Fatalf("首个候选 = %q", candidates[0])
|
|
}
|
|
}
|
|
|
|
func TestUpdateQrCodeRejectsUsedToUnused(t *testing.T) {
|
|
db := setupQrCodeTestDB(t)
|
|
repo := NewRepository(db, nil)
|
|
now := time.Date(2026, 6, 18, 12, 0, 0, 0, time.UTC)
|
|
conversationID := uint64(1001)
|
|
qrcode := model.ChatQrCode{
|
|
ImageURL: "/api/files/object?key=qrcode/used.png",
|
|
Status: QrCodeStatusUsed,
|
|
ConversationID: &conversationID,
|
|
UsedAt: &now,
|
|
CreatedBy: 1,
|
|
}
|
|
if err := db.Create(&qrcode).Error; err != nil {
|
|
t.Fatalf("创建二维码失败: %v", err)
|
|
}
|
|
|
|
status := QrCodeStatusUnused
|
|
err := repo.UpdateQrCode(t.Context(), qrcode.ID, UpdateQrCodeRequest{Status: &status})
|
|
if !errors.Is(err, ErrQrCodeCannotReenable) {
|
|
t.Fatalf("error = %v, want ErrQrCodeCannotReenable", err)
|
|
}
|
|
|
|
var saved model.ChatQrCode
|
|
if err := db.First(&saved, qrcode.ID).Error; err != nil {
|
|
t.Fatalf("查询二维码失败: %v", err)
|
|
}
|
|
if saved.Status != QrCodeStatusUsed {
|
|
t.Fatalf("二维码状态 = %q, want %q", saved.Status, QrCodeStatusUsed)
|
|
}
|
|
}
|
|
|
|
func TestUpdateQrCodeRejectsIssuedDisabledToUnused(t *testing.T) {
|
|
db := setupQrCodeTestDB(t)
|
|
repo := NewRepository(db, nil)
|
|
conversationID := uint64(1002)
|
|
qrcode := model.ChatQrCode{
|
|
ImageURL: "/api/files/object?key=qrcode/disabled.png",
|
|
Status: QrCodeStatusDisabled,
|
|
ConversationID: &conversationID,
|
|
CreatedBy: 1,
|
|
}
|
|
if err := db.Create(&qrcode).Error; err != nil {
|
|
t.Fatalf("创建二维码失败: %v", err)
|
|
}
|
|
|
|
status := QrCodeStatusUnused
|
|
err := repo.UpdateQrCode(t.Context(), qrcode.ID, UpdateQrCodeRequest{Status: &status})
|
|
if !errors.Is(err, ErrQrCodeCannotReenable) {
|
|
t.Fatalf("error = %v, want ErrQrCodeCannotReenable", err)
|
|
}
|
|
}
|
|
|
|
func TestUpdateQrCodeAllowsUnusedToDisabled(t *testing.T) {
|
|
db := setupQrCodeTestDB(t)
|
|
repo := NewRepository(db, nil)
|
|
qrcode := model.ChatQrCode{
|
|
ImageURL: "/api/files/object?key=qrcode/unused.png",
|
|
Status: QrCodeStatusUnused,
|
|
CreatedBy: 1,
|
|
}
|
|
if err := db.Create(&qrcode).Error; err != nil {
|
|
t.Fatalf("创建二维码失败: %v", err)
|
|
}
|
|
|
|
status := QrCodeStatusDisabled
|
|
if err := repo.UpdateQrCode(t.Context(), qrcode.ID, UpdateQrCodeRequest{Status: &status}); err != nil {
|
|
t.Fatalf("更新二维码失败: %v", err)
|
|
}
|
|
|
|
var saved model.ChatQrCode
|
|
if err := db.First(&saved, qrcode.ID).Error; err != nil {
|
|
t.Fatalf("查询二维码失败: %v", err)
|
|
}
|
|
if saved.Status != QrCodeStatusDisabled {
|
|
t.Fatalf("二维码状态 = %q, want %q", saved.Status, QrCodeStatusDisabled)
|
|
}
|
|
}
|
|
|
|
func TestUpdateQrCodeGroupNameAndRenameFlag(t *testing.T) {
|
|
db := setupQrCodeTestDB(t)
|
|
repo := NewRepository(db, nil)
|
|
qrcode := model.ChatQrCode{
|
|
ImageURL: "/api/files/object?key=qrcode/unused.png",
|
|
Status: QrCodeStatusUnused,
|
|
CreatedBy: 1,
|
|
}
|
|
if err := db.Create(&qrcode).Error; err != nil {
|
|
t.Fatalf("创建二维码失败: %v", err)
|
|
}
|
|
|
|
groupName := "王大锤-鼠鼠跑刀一群"
|
|
renamed := true
|
|
if err := repo.UpdateQrCode(t.Context(), qrcode.ID, UpdateQrCodeRequest{
|
|
GroupName: &groupName,
|
|
WecomRenamed: &renamed,
|
|
}); err != nil {
|
|
t.Fatalf("更新二维码失败: %v", err)
|
|
}
|
|
|
|
var saved model.ChatQrCode
|
|
if err := db.First(&saved, qrcode.ID).Error; err != nil {
|
|
t.Fatalf("查询二维码失败: %v", err)
|
|
}
|
|
if saved.GroupName != groupName {
|
|
t.Fatalf("群名 = %q, want %q", saved.GroupName, groupName)
|
|
}
|
|
if !saved.WecomRenamed {
|
|
t.Fatal("企微改名标记未保存")
|
|
}
|
|
}
|