102 lines
3.2 KiB
C#
102 lines
3.2 KiB
C#
using System.Reflection;
|
|
using GmRelay.Bot.Infrastructure.Telegram;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using Telegram.Bot.Types;
|
|
using Telegram.Bot.Types.Enums;
|
|
|
|
namespace GmRelay.Bot.Tests.Infrastructure.Telegram;
|
|
|
|
public sealed class TelegramBotServiceTests
|
|
{
|
|
[Fact]
|
|
public async Task ExecuteAsync_ShouldStartPollingAfterLastPendingUpdate()
|
|
{
|
|
using var cts = new CancellationTokenSource();
|
|
var updateSource = new FakeTelegramUpdateSource(cts);
|
|
var updateHandler = new FakeTelegramUpdateHandler();
|
|
var service = new TelegramBotService(
|
|
updateSource,
|
|
updateHandler,
|
|
NullLogger<TelegramBotService>.Instance);
|
|
|
|
await InvokeExecuteAsync(service, cts.Token);
|
|
|
|
Assert.Empty(updateHandler.HandledUpdates);
|
|
Assert.Collection(
|
|
updateSource.Calls,
|
|
call =>
|
|
{
|
|
Assert.Equal(-1, call.Offset);
|
|
Assert.Equal(1, call.Limit);
|
|
Assert.Null(call.Timeout);
|
|
Assert.Null(call.AllowedUpdates);
|
|
},
|
|
call =>
|
|
{
|
|
Assert.Equal(43, call.Offset);
|
|
Assert.Null(call.Limit);
|
|
Assert.Equal(30, call.Timeout);
|
|
Assert.Equal([UpdateType.Message, UpdateType.CallbackQuery], call.AllowedUpdates);
|
|
});
|
|
}
|
|
|
|
private static async Task InvokeExecuteAsync(TelegramBotService service, CancellationToken cancellationToken)
|
|
{
|
|
var executeAsync = typeof(TelegramBotService).GetMethod(
|
|
"ExecuteAsync",
|
|
BindingFlags.Instance | BindingFlags.NonPublic);
|
|
|
|
Assert.NotNull(executeAsync);
|
|
|
|
var task = executeAsync.Invoke(service, [cancellationToken]) as Task;
|
|
Assert.NotNull(task);
|
|
|
|
await task;
|
|
}
|
|
|
|
private sealed class FakeTelegramUpdateHandler : ITelegramUpdateHandler
|
|
{
|
|
public List<Update> HandledUpdates { get; } = [];
|
|
|
|
public Task RouteAsync(Update update, CancellationToken ct)
|
|
{
|
|
HandledUpdates.Add(update);
|
|
return Task.CompletedTask;
|
|
}
|
|
}
|
|
|
|
private sealed class FakeTelegramUpdateSource(CancellationTokenSource cts) : ITelegramUpdateSource
|
|
{
|
|
public List<PollCall> Calls { get; } = [];
|
|
|
|
public Task<Update[]> GetUpdatesAsync(
|
|
int offset,
|
|
int? limit = null,
|
|
int? timeout = null,
|
|
IEnumerable<UpdateType>? allowedUpdates = null,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
Calls.Add(new PollCall(offset, limit, timeout, allowedUpdates?.ToArray()));
|
|
|
|
return Calls.Count switch
|
|
{
|
|
1 => Task.FromResult(new[] { new Update { Id = 42 } }),
|
|
2 => ReturnAndCancelAsync(),
|
|
_ => throw new InvalidOperationException("Unexpected polling call.")
|
|
};
|
|
}
|
|
|
|
private Task<Update[]> ReturnAndCancelAsync()
|
|
{
|
|
cts.Cancel();
|
|
return Task.FromResult(Array.Empty<Update>());
|
|
}
|
|
}
|
|
|
|
private sealed record PollCall(
|
|
int Offset,
|
|
int? Limit,
|
|
int? Timeout,
|
|
UpdateType[]? AllowedUpdates);
|
|
}
|