DeleteFriend 一次删掉两条好友边,消息仍留在会话里。 Co-authored-by: Cursor <cursoragent@cursor.com>
178 lines
5.4 KiB
Go
178 lines
5.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)
|
|
}
|
|
peer, err := svc.GetFollow(ctx, b.ID, a.ID)
|
|
if err != nil || peer.Friend || peer.Mutual {
|
|
t.Fatalf("peer %+v %v", peer, err)
|
|
}
|
|
if _, err := svc.Relation(ctx, a.ID, b.ID); !errors.Is(err, errs.ErrNotFound) {
|
|
t.Fatalf("edge a->b %v", err)
|
|
}
|
|
if _, err := svc.Relation(ctx, b.ID, a.ID); !errors.Is(err, errs.ErrNotFound) {
|
|
t.Fatalf("edge b->a %v", 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)
|
|
}
|
|
}
|
|
|
|
func TestOtherSideUnfollowRemovesBothEdges(t *testing.T) {
|
|
svc, users, _ := testFriends(t)
|
|
ctx := t.Context()
|
|
a, b := twoUsers(t, users)
|
|
if _, err := svc.Follow(ctx, a.ID, b.ID); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if view, err := svc.Follow(ctx, b.ID, a.ID); err != nil || !view.Friend {
|
|
t.Fatalf("mutual %+v %v", view, err)
|
|
}
|
|
view, err := svc.Unfollow(ctx, b.ID, a.ID)
|
|
if err != nil || view.Friend || view.Mutual {
|
|
t.Fatalf("unfollow %+v %v", view, err)
|
|
}
|
|
if _, err := svc.Relation(ctx, a.ID, b.ID); !errors.Is(err, errs.ErrNotFound) {
|
|
t.Fatalf("edge a->b %v", err)
|
|
}
|
|
if _, err := svc.Relation(ctx, b.ID, a.ID); !errors.Is(err, errs.ErrNotFound) {
|
|
t.Fatalf("edge b->a %v", err)
|
|
}
|
|
left, err := svc.GetFollow(ctx, a.ID, b.ID)
|
|
if err != nil || left.Friend || !left.Following {
|
|
t.Fatalf("remaining follow %+v %v", left, 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)
|
|
}
|
|
}
|