feat: extract MyAgent core and web console
This commit is contained in:
commit
e491b1a35b
83 files changed
+13651
No files matched your search
@@ -0,0 +1,91 @@
|
||||
using Microsoft.Extensions.Options;
|
||||
using MyAgent.Core;
|
||||
using Xunit;
|
||||
|
||||
namespace MyAgent.Tests.Core;
|
||||
|
||||
public sealed class SessionManagerTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task DebounceAsync_TwoRapidMessagesProduceOneStableBatch()
|
||||
{
|
||||
var manager = CreateManager();
|
||||
var now = DateTimeOffset.Now;
|
||||
var first = manager.DebounceAsync(CreateMessage("1", "第一条", now));
|
||||
await Task.Delay(10);
|
||||
var second = manager.DebounceAsync(CreateMessage("2", "第二条", now.AddMilliseconds(10)));
|
||||
|
||||
Assert.Null(await first);
|
||||
var batch = await second;
|
||||
Assert.NotNull(batch);
|
||||
Assert.Equal(2, batch!.Messages.Count);
|
||||
Assert.Contains("第一条", batch.MergedText);
|
||||
Assert.Contains("第二条", batch.MergedText);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DebounceAsync_CompletedBatchIsConsumed()
|
||||
{
|
||||
var manager = CreateManager();
|
||||
var first = await manager.DebounceAsync(CreateMessage("1", "第一轮", DateTimeOffset.Now));
|
||||
var second = await manager.DebounceAsync(CreateMessage("2", "第二轮", DateTimeOffset.Now.AddSeconds(1)));
|
||||
|
||||
Assert.Single(first!.Messages);
|
||||
Assert.Single(second!.Messages);
|
||||
Assert.Equal("第二轮", second.MergedText);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DebounceAsync_CallerCancellationDoesNotLeaveBrokenPendingState()
|
||||
{
|
||||
var manager = CreateManager();
|
||||
using var cancellation = new CancellationTokenSource();
|
||||
var cancelled = manager.DebounceAsync(CreateMessage("1", "取消", DateTimeOffset.Now), cancellation.Token);
|
||||
cancellation.Cancel();
|
||||
|
||||
await Assert.ThrowsAnyAsync<OperationCanceledException>(() => cancelled);
|
||||
var next = await manager.DebounceAsync(CreateMessage("2", "下一条", DateTimeOffset.Now.AddSeconds(1)));
|
||||
|
||||
Assert.NotNull(next);
|
||||
Assert.Single(next!.Messages);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DebounceAsync_DifferentUsersReplyingToSameMessageStayIsolated()
|
||||
{
|
||||
var manager = CreateManager();
|
||||
var firstMessage = CreateMessage("1", "用户一", DateTimeOffset.Now, "1", "root");
|
||||
var secondMessage = CreateMessage("2", "用户二", DateTimeOffset.Now, "2", "root");
|
||||
|
||||
var first = manager.DebounceAsync(firstMessage);
|
||||
var second = manager.DebounceAsync(secondMessage);
|
||||
var batches = await Task.WhenAll(first, second);
|
||||
|
||||
Assert.All(batches, batch => Assert.Single(batch!.Messages));
|
||||
Assert.NotEqual(batches[0]!.ThreadId, batches[1]!.ThreadId);
|
||||
}
|
||||
|
||||
private static SessionManager CreateManager()
|
||||
{
|
||||
var options = Options.Create(new ShirobotOptions
|
||||
{
|
||||
Fusion = new FusionOptions
|
||||
{
|
||||
DebounceMs = 40,
|
||||
SameUserMergeWindowSec = 8,
|
||||
MaxMergedMessages = 8
|
||||
}
|
||||
});
|
||||
return new SessionManager(options, TimeProvider.System);
|
||||
}
|
||||
|
||||
private static IncomingMessage CreateMessage(string id, string text, DateTimeOffset at, string userId = "1", string? replyToMessageId = null) => new()
|
||||
{
|
||||
MessageId = id,
|
||||
GroupId = "1",
|
||||
UserId = userId,
|
||||
Text = text,
|
||||
CreatedAt = at,
|
||||
ReplyToMessageId = replyToMessageId
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user