spark-server/internal/module/friend/logic/follow_test.go
DESKTOP-L8OUL9F\gfl0034 ce9c7a13aa feat: 互相关注后自动成为好友
一方关注只记关注。双方互关时写入已有双向好友边;取消关注若不再互关只删好友边,不删消息。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-18 21:51:18 +08:00

146 lines
4.4 KiB
Go

package logic
import (
"errors"
"testing"
"spark-server/internal/infrastructure/id"
convlogic "spark-server/internal/module/conversation/logic"
convmodel "spark-server/internal/module/conversation/model"
"spark-server/internal/module/friend/entity"
friendmodel "spark-server/internal/module/friend/model"
msgmodel "spark-server/internal/module/message/model"
userentity "spark-server/internal/module/user/entity"
"spark-server/internal/module/user/logictest"
"spark-server/internal/pkg/errs"
)
func TestOneWayFollowDoesNotFriend(t *testing.T) {
svc, users, g := testFriends(t)
ctx := t.Context()
a, b := twoUsers(t, users)
view, err := svc.Follow(ctx, a.ID, b.ID)
if err != nil || !view.Following || view.FollowedBy || view.Mutual || view.Friend {
t.Fatalf("%+v %v", view, err)
}
if g.n != 0 {
t.Fatalf("greeting %d", g.n)
}
ok, err := svc.AreFriends(ctx, a.ID, b.ID)
if err != nil || ok {
t.Fatalf("friends %v %v", ok, err)
}
}
func TestMutualFollowCreatesFriendsOnce(t *testing.T) {
svc, users, g := testFriends(t)
ctx := t.Context()
a, b := twoUsers(t, users)
if _, err := svc.Follow(ctx, a.ID, b.ID); err != nil {
t.Fatal(err)
}
view, err := svc.Follow(ctx, b.ID, a.ID)
if err != nil || !view.Mutual || !view.Friend || !view.Following || !view.FollowedBy {
t.Fatalf("%+v %v", view, err)
}
if g.n != 1 {
t.Fatalf("greeting %d", g.n)
}
again, err := svc.Follow(ctx, b.ID, a.ID)
if err != nil || !again.Friend || g.n != 1 {
t.Fatalf("repeat %+v greet %d %v", again, g.n, err)
}
rel, err := svc.Relation(ctx, a.ID, b.ID)
if err != nil || rel.Source != entity.SourceFollow {
t.Fatalf("source %+v %v", rel, err)
}
}
func TestUnfollowMutualDropsFriendsKeepsMessage(t *testing.T) {
ids, err := id.New(1)
if err != nil {
t.Fatal(err)
}
users := logictest.Users(ids, nil)
ctx := t.Context()
a, err := users.AuthenticateEmail(ctx, "test01@spark.com", "1", &userentity.LoginDevice{DeviceID: 1, DeviceType: userentity.DeviceIOS})
if err != nil {
t.Fatal(err)
}
b, err := users.AuthenticateEmail(ctx, "test02@spark.com", "1", &userentity.LoginDevice{DeviceID: 2, DeviceType: userentity.DeviceWeb})
if err != nil {
t.Fatal(err)
}
chats := convmodel.NewMemoryP2P()
msgs := msgmodel.NewMemoryRepo()
p2p := convlogic.NewP2PService(chats, ids)
svc := NewService(friendmodel.NewMemoryRepo(), users, ids, NewGreeter(p2p, msgs, ids, nil))
if _, err := svc.Follow(ctx, a.ID, b.ID); err != nil {
t.Fatal(err)
}
if _, err := svc.Follow(ctx, b.ID, a.ID); err != nil {
t.Fatal(err)
}
conv, err := chats.GetP2P(ctx, a.ID, b.ID)
if err != nil || conv == nil || conv.ID <= 0 {
t.Fatalf("conversation %+v %v", conv, err)
}
before, err := msgs.ListByConversation(ctx, conv.ID, a.ID, 0, 20)
if err != nil || len(before) != 1 {
t.Fatalf("before %d %v", len(before), err)
}
view, err := svc.Unfollow(ctx, a.ID, b.ID)
if err != nil || view.Following || view.Mutual || view.Friend || !view.FollowedBy {
t.Fatalf("%+v %v", view, err)
}
after, err := msgs.ListByConversation(ctx, conv.ID, a.ID, 0, 20)
if err != nil || len(after) != 1 || after[0].ID != before[0].ID {
t.Fatalf("after %d %v", len(after), err)
}
ok, err := svc.AreFriends(ctx, a.ID, b.ID)
if err != nil || ok {
t.Fatalf("still friends %v %v", ok, err)
}
}
func TestUnfollowOneWayKeepsAcceptedFriend(t *testing.T) {
svc, users, g := testFriends(t)
ctx := t.Context()
a, b := twoUsers(t, users)
applied, err := svc.Apply(ctx, a.ID, &ApplyInput{UID: b.ID})
if err != nil {
t.Fatal(err)
}
if _, err := svc.Accept(ctx, b.ID, AcceptInput{RequestID: applied.RequestID}); err != nil {
t.Fatal(err)
}
if _, err := svc.Follow(ctx, a.ID, b.ID); err != nil {
t.Fatal(err)
}
view, err := svc.Unfollow(ctx, a.ID, b.ID)
if err != nil || view.Following || !view.Friend || view.Mutual {
t.Fatalf("%+v %v", view, err)
}
if g.n != 1 {
t.Fatalf("greeting %d", g.n)
}
}
func TestFollowRejectsSelfAndBlock(t *testing.T) {
svc, users, _ := testFriends(t)
ctx := t.Context()
a, b := twoUsers(t, users)
if _, err := svc.Follow(ctx, a.ID, a.ID); !errors.Is(err, errs.ErrInvalidArgument) {
t.Fatalf("self %v", err)
}
if err := svc.Block(ctx, a.ID, b.ID); err != nil {
t.Fatal(err)
}
if _, err := svc.Follow(ctx, a.ID, b.ID); !errors.Is(err, errs.ErrForbidden) {
t.Fatalf("blocked by me %v", err)
}
if _, err := svc.Follow(ctx, b.ID, a.ID); !errors.Is(err, errs.ErrNotFound) {
t.Fatalf("blocked by peer %v", err)
}
}