using IM.Domain.Entities; using IM.Domain.Enums; using IM.Infrastructure.Persistence; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; namespace BuildFlow.IM.Integration.Tests; /// /// 集成测试数据播种助手。直接写真实 PostgreSQL,构造会话/群组/群成员, /// 供 ChatHub 与 MediatR handler 读写。 /// public static class ImTestSeeder { /// /// 播种一个私聊会话(两参与者),返回会话 ID。 /// public static async Task SeedPrivateConversationAsync(ImServerFixture fixture, Guid userA, Guid userB) { await using var scope = fixture.Services.CreateAsyncScope(); var db = scope.ServiceProvider.GetRequiredService(); var conv = new Conversation { Type = ConversationType.Private }; conv.Participants = [ new ConversationParticipant { ConversationId = conv.Id, UserId = userA, JoinedAt = DateTime.UtcNow }, new ConversationParticipant { ConversationId = conv.Id, UserId = userB, JoinedAt = DateTime.UtcNow }, ]; db.Conversations.Add(conv); await db.SaveChangesAsync(); return conv.Id; } /// /// 播种一个群聊会话:创建会话 + 群组 + 群成员,返回(会话ID, 群ID)。 /// 形如 (userId, role) 列表,决定每个成员的群角色(影响撤回权限)。 /// public static async Task<(Guid ConversationId, Guid GroupId)> SeedGroupConversationAsync( ImServerFixture fixture, string groupName, Guid ownerId, params (Guid UserId, GroupMemberRole Role)[] members) { await using var scope = fixture.Services.CreateAsyncScope(); var db = scope.ServiceProvider.GetRequiredService(); var conv = new Conversation { Type = ConversationType.Group }; var group = new Group { ConversationId = conv.Id, Name = groupName, OwnerId = ownerId, }; // 群成员同时是会话参与者(决定谁能收发消息) foreach (var (userId, _) in members) { conv.Participants.Add(new ConversationParticipant { ConversationId = conv.Id, UserId = userId, JoinedAt = DateTime.UtcNow, }); } foreach (var (userId, role) in members) { group.Members.Add(new GroupMember { GroupId = group.Id, UserId = userId, Role = role, JoinedAt = DateTime.UtcNow, }); } db.Conversations.Add(conv); db.Groups.Add(group); await db.SaveChangesAsync(); return (conv.Id, group.Id); } /// 读取某用户在某会话的 PG 未读数(冷备读路径,验证双写一致性)。 public static async Task GetPgUnreadAsync(ImServerFixture fixture, Guid conversationId, Guid userId) { await using var scope = fixture.Services.CreateAsyncScope(); var db = scope.ServiceProvider.GetRequiredService(); var p = await db.ConversationParticipants .AsNoTracking() .FirstAsync(p => p.ConversationId == conversationId && p.UserId == userId); return p.UnreadCount; } }