fix: skip stale pending updates on startup
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user