package auth_test import ( "context" "fmt" "testing" "github.com/wangjia/pangolin/server/internal/auth" "github.com/wangjia/pangolin/server/internal/notices" ) // TestCreateUserWithTrial_InsertsWelcomeNotice: 注册同事务应插入一条欢迎到账通知, // 双语文案按 trialDays 参数化。用真实 notices.Store(而非 fake)验证落库结果; // 放在外部测试包(package auth_test)是因为 notices 反向 import auth(handler.go), // 若同包(package auth)测试文件再 import notices 会成环 —— 参照 store_sqlite_test.go // 里 fakeNoticer 单测的注释。 func TestCreateUserWithTrial_InsertsWelcomeNotice(t *testing.T) { db := auth.OpenAuthDBForTest(t) s := auth.NewSQLStore(db) s.SetNoticer(notices.NewStore(db)) u, err := s.CreateUserWithTrial(context.Background(), "welcome@example.com", "hash", 7) if err != nil { t.Fatalf("CreateUserWithTrial: %v", err) } var n int if err := db.QueryRow(`SELECT COUNT(*) FROM notices WHERE type='reward' AND user_id=?`, u.ID).Scan(&n); err != nil { t.Fatal(err) } if n != 1 { t.Fatalf("welcome notice count = %d, want 1", n) } var typ, titleZH, titleEN, bodyZH, bodyEN string row := db.QueryRow(`SELECT type, title_zh, title_en, body_zh, body_en FROM notices WHERE user_id=?`, u.ID) if err := row.Scan(&typ, &titleZH, &titleEN, &bodyZH, &bodyEN); err != nil { t.Fatal(err) } if typ != "reward" { t.Fatalf("type = %q, want reward", typ) } if titleZH != "欢迎加入 Pangolin 🎉" { t.Fatalf("titleZH = %q", titleZH) } if titleEN != "Welcome to Pangolin 🎉" { t.Fatalf("titleEN = %q", titleEN) } wantBodyZH := fmt.Sprintf("已为你开通 %d 天 PRO 会员,现在就选节点连接,畅享全球网络。", 7) if bodyZH != wantBodyZH { t.Fatalf("bodyZH = %q, want %q", bodyZH, wantBodyZH) } wantBodyEN := fmt.Sprintf("Your %d-day PRO trial is active. Pick a node and connect to enjoy unrestricted access.", 7) if bodyEN != wantBodyEN { t.Fatalf("bodyEN = %q, want %q", bodyEN, wantBodyEN) } } // TestCreateUserWithTrial_DupEmail_NoNotice: 邮箱重复 → 用户插入失败(事务回滚), // 不应留下任何通知(零孤儿)。 func TestCreateUserWithTrial_DupEmail_NoNotice(t *testing.T) { db := auth.OpenAuthDBForTest(t) s := auth.NewSQLStore(db) s.SetNoticer(notices.NewStore(db)) if _, err := s.CreateUserWithTrial(context.Background(), "dup@example.com", "hash", 7); err != nil { t.Fatalf("first CreateUserWithTrial: %v", err) } if _, err := s.CreateUserWithTrial(context.Background(), "dup@example.com", "hash2", 7); err != auth.ErrEmailTaken { t.Fatalf("second CreateUserWithTrial err = %v, want ErrEmailTaken", err) } var n int if err := db.QueryRow(`SELECT COUNT(*) FROM notices`).Scan(&n); err != nil { t.Fatal(err) } if n != 1 { t.Fatalf("notices count = %d, want 1 (only the first registration's welcome notice)", n) } }