Files
2026-04-04 05:01:51 +02:00

193 lines
8.0 KiB
C#

using Luna.Channels.Abstractions;
using Luna.Channels.Tests.Stubs;
using Luna.Core.Abstractions;
using Luna.Shared;
using Moq;
namespace Luna.Channels.Tests;
[TestFixture]
[Category("Unit")]
public class IntegrationTests
{
private Mock<ISessionManager> sessionManagerMock = null!;
private Mock<IChannel> channelMock = null!;
private ChannelManagerStub manager = null!;
[SetUp]
public void SetUp()
{
sessionManagerMock = new Mock<ISessionManager>();
channelMock = new Mock<IChannel>();
channelMock.Setup(c => c.ChannelId).Returns("test-ch-1");
channelMock.Setup(c => c.ChannelType).Returns("test");
channelMock.Setup(c => c.SendStreamingMessageAsync(
It.IsAny<IAsyncEnumerable<ChatStreamUpdate>>(),
It.IsAny<CancellationToken>())).Returns(Task.CompletedTask);
manager = new ChannelManagerStub(sessionManagerMock.Object);
}
private static async IAsyncEnumerable<ChatStreamUpdate> BuildStream(params ChatStreamUpdate[] updates)
{
foreach (var u in updates)
{
yield return u;
await Task.Yield();
}
}
[Test]
public async Task MessageReceived_RoutesToSessionManager_WithCorrectContent()
{
var message = new ChannelMessage(
Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "user-1", "User One", "Hello Luna!", DateTimeOffset.UtcNow);
sessionManagerMock
.Setup(s => s.RouteMessagesAsync(
message.Content,
message.ConversationId,
It.IsAny<string>(),
It.IsAny<CancellationToken>()))
.Returns(BuildStream(new ChatStreamUpdate(ChatStreamUpdateType.Text, "Hi!", null, false)));
manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" });
var args = new ChannelMessageReceivedEventArgs { Message = message, Channel = channelMock.Object };
channelMock.Raise(c => c.MessageReceived += null, channelMock.Object, args);
await Task.Delay(50);
sessionManagerMock.Verify(s => s.RouteMessagesAsync(
message.Content,
message.ConversationId,
It.IsAny<string>(),
It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public async Task MessageReceived_PipesSessionResponseToChannel_SendStreamingMessageAsync()
{
var message = new ChannelMessage(
Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "user-2", "User Two", "What time is it?", DateTimeOffset.UtcNow);
var responseStream = BuildStream(
new ChatStreamUpdate(ChatStreamUpdateType.Text, "It's ", null, false),
new ChatStreamUpdate(ChatStreamUpdateType.Text, "noon.", null, false),
new ChatStreamUpdate(ChatStreamUpdateType.Complete, null, null, true));
sessionManagerMock
.Setup(s => s.RouteMessagesAsync(
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Returns(responseStream);
manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" });
var args = new ChannelMessageReceivedEventArgs { Message = message, Channel = channelMock.Object };
channelMock.Raise(c => c.MessageReceived += null, channelMock.Object, args);
await Task.Delay(50);
channelMock.Verify(c => c.SendStreamingMessageAsync(
It.IsAny<IAsyncEnumerable<ChatStreamUpdate>>(),
It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public async Task MessageReceived_WhenIsHandled_True_DoesNotRouteToSessionManager()
{
var message = new ChannelMessage(
Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "user-3", "User Three", "/start", DateTimeOffset.UtcNow);
manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" });
var args = new ChannelMessageReceivedEventArgs { Message = message, Channel = channelMock.Object, IsHandled = true };
channelMock.Raise(c => c.MessageReceived += null, channelMock.Object, args);
await Task.Delay(50);
sessionManagerMock.Verify(s => s.RouteMessagesAsync(
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()),
Times.Never);
}
[Test]
public async Task TwoChannels_ReceiveMessagesIndependently_BothRoutedToSessionManager()
{
var channel2Mock = new Mock<IChannel>();
channel2Mock.Setup(c => c.ChannelId).Returns("test-ch-2");
channel2Mock.Setup(c => c.ChannelType).Returns("test");
channel2Mock.Setup(c => c.SendStreamingMessageAsync(
It.IsAny<IAsyncEnumerable<ChatStreamUpdate>>(), It.IsAny<CancellationToken>()))
.Returns(Task.CompletedTask);
sessionManagerMock
.Setup(s => s.RouteMessagesAsync(
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Returns(BuildStream(new ChatStreamUpdate(ChatStreamUpdateType.Text, "ok", null, true)));
manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" });
manager.RegisterChannel(channel2Mock.Object);
var msg1 = new ChannelMessage(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "u1", "U1", "Msg1", DateTimeOffset.UtcNow);
var msg2 = new ChannelMessage(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "u2", "U2", "Msg2", DateTimeOffset.UtcNow);
channelMock.Raise(c => c.MessageReceived += null, channelMock.Object,
new ChannelMessageReceivedEventArgs { Message = msg1, Channel = channelMock.Object });
channel2Mock.Raise(c => c.MessageReceived += null, channel2Mock.Object,
new ChannelMessageReceivedEventArgs { Message = msg2, Channel = channel2Mock.Object });
await Task.Delay(100);
sessionManagerMock.Verify(s => s.RouteMessagesAsync(
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()),
Times.Exactly(2));
}
[Test]
public async Task SessionManager_RouteMessagesAsync_ReceivesCancellationToken()
{
using var cts = new CancellationTokenSource();
var message = new ChannelMessage(
Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "user-4", "User Four", "Cancel me", DateTimeOffset.UtcNow);
sessionManagerMock
.Setup(s => s.RouteMessagesAsync(
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), cts.Token))
.Returns(BuildStream(new ChatStreamUpdate(ChatStreamUpdateType.Text, "x", null, true)));
manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" });
var args = new ChannelMessageReceivedEventArgs { Message = message, Channel = channelMock.Object };
await channelMock.RaiseAsync(c => c.MessageReceived += null, channelMock.Object, args);
await Task.Delay(50, cts.Token);
sessionManagerMock.Verify(s => s.RouteMessagesAsync(
message.Content,
message.ConversationId,
It.IsAny<string>(),
It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public async Task SessionManager_Throws_ChannelRemainsActive_NotDisconnected()
{
var message = new ChannelMessage(
Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "user-5", "User Five", "Boom", DateTimeOffset.UtcNow);
sessionManagerMock
.Setup(s => s.RouteMessagesAsync(
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Throws(new InvalidOperationException("Simulated routing failure"));
manager.RegisterChannel(new CliChannelStub { ChannelId = "test-1" });
Assert.DoesNotThrowAsync(async () =>
{
var args = new ChannelMessageReceivedEventArgs { Message = message, Channel = channelMock.Object };
await channelMock.RaiseAsync(c => c.MessageReceived += null, channelMock.Object, args);
await Task.Delay(50);
});
}
}