forked from admin/VolcanicAgenticCore
111 lines
4.8 KiB
C#
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);
|
|
}
|
|
}
|