using Microsoft.Extensions.Logging.Abstractions; using Telegram.Bot.Exceptions; using Telegram.Bot.Requests; using Telegram.Bot.Requests.Abstractions; using Volcanic.AgenticCore.Telegram.Rendering; using Volcanic.AgenticCore.Telegram.Tests.Support; namespace Volcanic.AgenticCore.Telegram.Tests; public sealed class BotSetupServiceTests { private static (BotSetupService Service, FakeBotClient Bot) Create(Action? onSend) { var bot = new FakeBotClient { OnSend = onSend }; var options = new TelegramOptions { BotToken = "t", AllowedUserIds = [Updates.AllowedUser, 2002], ReconnectInitialDelay = TimeSpan.FromMilliseconds(5), ReconnectMaxDelay = TimeSpan.FromMilliseconds(20), }; var sender = new TelegramSender(bot, NullLogger.Instance); return (new BotSetupService(bot, options, sender, NullLogger.Instance), bot); } [Fact] public async Task Online_goes_once_to_the_owner_after_setup_succeeds_on_the_second_try() { var getMeCalls = 0; var (service, bot) = Create(r => { if (r is GetMeRequest && Interlocked.Increment(ref getMeCalls) == 1) throw FakeBotClient.NetworkDown(); }); await service.StartAsync(CancellationToken.None); await service.ExecuteTask!.WaitAsync(TimeSpan.FromSeconds(5)); await service.StopAsync(CancellationToken.None); Assert.Equal(2, bot.Requests.OfType().Count()); var online = Assert.Single(bot.Sent); Assert.Equal(Updates.AllowedUser, online.ChatId.Identifier); Assert.Equal("🟢 Online.", online.Text); } [Fact] public async Task A_forbidden_online_message_is_not_retried_and_does_not_stop_the_service() { var (service, bot) = Create(r => { if (r is SendMessageRequest) throw new ApiRequestException("Forbidden: bot can't initiate conversation with a user", 403); }); await service.StartAsync(CancellationToken.None); await service.ExecuteTask!.WaitAsync(TimeSpan.FromSeconds(5)); Assert.True(service.ExecuteTask.IsCompletedSuccessfully); Assert.Single(bot.Requests.OfType()); Assert.Single(bot.Requests.OfType()); await service.StopAsync(CancellationToken.None); } [Fact] public async Task The_admins_chat_menu_also_lists_impersonate() { var bot = new FakeBotClient(); var options = new TelegramOptions { BotToken = "t", AllowedUserIds = [Updates.AllowedUser], AdminUserId = 5005 }; var service = new BotSetupService(bot, options, new TelegramSender(bot, NullLogger.Instance), NullLogger.Instance); await service.StartAsync(CancellationToken.None); await service.ExecuteTask!.WaitAsync(TimeSpan.FromSeconds(5)); await service.StopAsync(CancellationToken.None); var menus = bot.Requests.OfType().ToList(); Assert.Equal(2, menus.Count); Assert.DoesNotContain(menus[0].Commands, c => c.Command == "impersonate"); var admin = Assert.IsType(menus[1].Scope); Assert.Equal(5005, admin.ChatId.Identifier); Assert.Contains(menus[1].Commands, c => c.Command == "impersonate"); } }