forked from admin/VolcanicAgenticCore
88 lines
3.8 KiB
C#
88 lines
3.8 KiB
C#
using Volcanic.AgenticCore.Telegram.Chats;
|
|
using Volcanic.AgenticCore.Telegram.Rendering;
|
|
|
|
namespace Volcanic.AgenticCore.Telegram.Tests;
|
|
|
|
public sealed class FormattingAndOptionsTests
|
|
{
|
|
[Theory]
|
|
[InlineData("a < b & c > d", "a < b & c > d")]
|
|
[InlineData("**bold** and *it* and _it_", "<b>bold</b> and <i>it</i> and <i>it</i>")]
|
|
[InlineData("use `x < 1` here", "use <code>x < 1</code> here")]
|
|
[InlineData("`**not bold**`", "<code>**not bold**</code>")]
|
|
[InlineData("snake_case_name stays", "snake_case_name stays")]
|
|
[InlineData("# Title", "<b>Title</b>")]
|
|
[InlineData("- item", "• item")]
|
|
[InlineData("[docs](https://example.com/a?b=1&c=2)", "<a href=\"https://example.com/a?b=1&c=2\">docs</a>")]
|
|
[InlineData("~~gone~~", "<s>gone</s>")]
|
|
[InlineData("🆕 Привет \"quoted\" it's", "🆕 Привет \"quoted\" it's")]
|
|
public void Markdown_becomes_telegram_html(string markdown, string html) =>
|
|
Assert.Equal(html, TelegramFormatter.ToHtml(markdown));
|
|
|
|
[Fact]
|
|
public void Code_blocks_keep_their_content_literal()
|
|
{
|
|
var html = TelegramFormatter.ToHtml("Run:\n```bash\necho \"<hi>\" **x**\n```\nDone.");
|
|
Assert.Equal("Run:\n<pre><code class=\"language-bash\">echo \"<hi>\" **x**</code></pre>\nDone.", html);
|
|
}
|
|
|
|
[Fact]
|
|
public void An_unterminated_code_block_while_streaming_is_still_well_formed()
|
|
{
|
|
Assert.Equal("<pre>partial <</pre>", TelegramFormatter.ToHtml("```\npartial <"));
|
|
}
|
|
|
|
[Fact]
|
|
public void Split_prefers_paragraphs_and_reopens_cut_code_blocks()
|
|
{
|
|
var code = string.Join("\n", Enumerable.Range(0, 40).Select(i => $"line {i}"));
|
|
var text = "intro\n\n```python\n" + code + "\n```\nafter";
|
|
|
|
var chunks = TelegramFormatter.Split(text, limit: 120);
|
|
|
|
Assert.True(chunks.Count > 2);
|
|
Assert.All(chunks, c => Assert.True(c.Length <= 120, $"{c.Length}: {c}"));
|
|
Assert.All(chunks, c => Assert.Equal(0, c.Split('\n').Count(l => l.StartsWith("```", StringComparison.Ordinal)) % 2));
|
|
Assert.StartsWith("```python\n", chunks[1]);
|
|
Assert.Equal(text.Replace("```python\n", "").Replace("```\n", "").Replace("\n", ""),
|
|
string.Concat(chunks.Select(c => string.Join("", c.Split('\n').Where(l => !l.StartsWith("```", StringComparison.Ordinal))))));
|
|
}
|
|
|
|
[Fact]
|
|
public void Short_text_is_one_chunk() => Assert.Equal(["hi"], TelegramFormatter.Split("hi"));
|
|
|
|
[Theory]
|
|
[InlineData("/stop", "stop", "")]
|
|
[InlineData("/resume@my_bot abc", "resume", "abc")]
|
|
[InlineData("/Thinking high ", "thinking", "high")]
|
|
public void Commands_parse(string text, string name, string args) => Assert.Equal((name, args), ChatCommands.Parse(text));
|
|
|
|
[Theory]
|
|
[InlineData("hello")]
|
|
[InlineData("/")]
|
|
public void Non_commands_do_not_parse(string text) => Assert.Null(ChatCommands.Parse(text));
|
|
|
|
[Fact]
|
|
public void An_empty_allow_list_is_rejected()
|
|
{
|
|
var errors = new TelegramOptions { BotToken = "t" }.Validate();
|
|
Assert.Contains(errors, e => e.Contains("allowed users", StringComparison.OrdinalIgnoreCase));
|
|
}
|
|
|
|
[Fact]
|
|
public void Environment_shortcuts_fill_the_token_and_users()
|
|
{
|
|
var env = new Dictionary<string, string> { ["TELEGRAM_BOT_TOKEN"] = "123:abc", ["TELEGRAM_ALLOWED_USER_IDS"] = "1, 2;3" };
|
|
var options = new TelegramOptions();
|
|
options.ApplyEnvironment(k => env.GetValueOrDefault(k));
|
|
|
|
Assert.Equal("123:abc", options.BotToken);
|
|
Assert.Equal([1L, 2L, 3L], options.AllowedUserIds);
|
|
Assert.Empty(options.Validate());
|
|
Assert.Equal("claude-code/claude-opus-5-5", options.Model);
|
|
Assert.True(options.IsAllowed(2));
|
|
Assert.False(options.IsAllowed(4));
|
|
Assert.False(options.IsAllowed(null));
|
|
}
|
|
}
|