Files
Playa/tests/Volcanic.AgenticCore.Telegram.Tests/TelegramSenderTests.cs

111 lines
4.8 KiB
C#

using Microsoft.Extensions.Logging.Abstractions;
using Telegram.Bot.Exceptions;
using Telegram.Bot.Requests;
using Telegram.Bot.Types;
using Telegram.Bot.Types.Enums;
using Volcanic.AgenticCore.Telegram.Rendering;
using Volcanic.AgenticCore.Telegram.Tests.Support;
namespace Volcanic.AgenticCore.Telegram.Tests;
public sealed class TelegramSenderTests
{
[Fact]
public async Task ReactAsync_sets_an_emoji_reaction()
{
var bot = new FakeBotClient();
var sender = new TelegramSender(bot, NullLogger<TelegramSender>.Instance);
await sender.ReactAsync(1001, 55, "👀");
var reaction = Assert.Single(bot.Reactions);
Assert.Equal(1001, reaction.ChatId.Identifier);
Assert.Equal(55, reaction.MessageId);
Assert.Equal("👀", Assert.IsType<ReactionTypeEmoji>(Assert.Single(reaction.Reaction!)).Emoji);
}
[Fact]
public async Task ReactAsync_swallows_failures()
{
var bot = new FakeBotClient { OnSend = r => { if (r is SetMessageReactionRequest) throw FakeBotClient.NetworkDown(); } };
var sender = new TelegramSender(bot, NullLogger<TelegramSender>.Instance);
await sender.ReactAsync(1001, 55, "👀"); // does not throw
Assert.Single(bot.Reactions);
}
private static (FakeBotClient Bot, TelegramSender Sender, string Path) FileSetup(string name = "chart.png")
{
var bot = new FakeBotClient();
var sender = new TelegramSender(bot, NullLogger<TelegramSender>.Instance) { FileRetryDelays = [TimeSpan.Zero, TimeSpan.Zero] };
var path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "volcanic-upload-" + Guid.NewGuid().ToString("N"), name);
Directory.CreateDirectory(System.IO.Path.GetDirectoryName(path)!);
System.IO.File.WriteAllBytes(path, [1, 2, 3]);
return (bot, sender, path);
}
[Fact]
public async Task SendFileAsync_uploads_a_photo_with_a_plain_caption()
{
var (bot, sender, path) = FileSetup();
var result = await sender.SendFileAsync(1001, path, asPhoto: true, caption: "<b>Sales</b>");
var upload = Assert.Single(bot.Uploads);
Assert.Equal(("sendPhoto", "chart.png", "<b>Sales</b>", ParseMode.None), (upload.Method, upload.FileName, upload.Caption, upload.ParseMode));
Assert.Equal(new byte[] { 1, 2, 3 }, upload.Bytes);
Assert.Equal(new TelegramSender.FileSendResult(upload.MessageId, null, false), result);
}
[Fact]
public async Task SendFileAsync_sends_a_document()
{
var (bot, sender, path) = FileSetup("report.pdf");
var result = await sender.SendFileAsync(1001, path, asPhoto: false, caption: null);
Assert.Equal("sendDocument", Assert.Single(bot.Uploads).Method);
Assert.NotNull(result.MessageId);
}
[Fact]
public async Task SendFileAsync_retries_a_network_failure_twice()
{
var (bot, sender, path) = FileSetup("report.pdf");
var failures = 2;
bot.OnSend = r => { if (r is SendDocumentRequest && failures-- > 0) throw FakeBotClient.NetworkDown(); };
var result = await sender.SendFileAsync(1001, path, asPhoto: false, caption: null);
Assert.NotNull(result.MessageId);
Assert.Equal(3, bot.Requests.OfType<SendDocumentRequest>().Count());
}
[Fact]
public async Task SendFileAsync_gives_up_after_two_retries()
{
var (bot, sender, path) = FileSetup("report.pdf");
bot.OnSend = r => { if (r is SendDocumentRequest) throw FakeBotClient.NetworkDown(); };
var result = await sender.SendFileAsync(1001, path, asPhoto: false, caption: null);
Assert.Null(result.MessageId);
Assert.NotNull(result.Error);
Assert.False(result.PhotoRejected);
Assert.Equal(3, bot.Requests.OfType<SendDocumentRequest>().Count());
}
[Fact]
public async Task A_400_on_sendPhoto_is_reported_as_PhotoRejected()
{
var (bot, sender, path) = FileSetup();
bot.OnSend = r => { if (r is SendPhotoRequest) throw new ApiRequestException("Bad Request: PHOTO_INVALID_DIMENSIONS", 400); };
var result = await sender.SendFileAsync(1001, path, asPhoto: true, caption: null);
Assert.True(result.PhotoRejected);
Assert.Contains("PHOTO_INVALID_DIMENSIONS", result.Error, StringComparison.Ordinal);
Assert.Single(bot.Requests.OfType<SendPhotoRequest>()); // an API error is not retried
}
[Fact]
public async Task A_400_on_sendDocument_is_an_error_not_a_rejected_photo()
{
var (bot, sender, path) = FileSetup("report.pdf");
bot.OnSend = r => { if (r is SendDocumentRequest) throw new ApiRequestException("Bad Request: file is empty", 400); };
var result = await sender.SendFileAsync(1001, path, asPhoto: false, caption: null);
Assert.Equal(new TelegramSender.FileSendResult(null, "Bad Request: file is empty", false), result);
}
}