#794: Telegram-Client-Anmeldung ueber die WebUI

Code und 2FA-Passwort wurden nur im Desktop-Dialog abgefragt; eine Instanz
ohne Fenster liess die Anmeldung aus. Jetzt haelt die Instanz die Frage
(TelegramLoginBroker), die Einstellungsseite beantwortet sie. Die Anmeldung
laeuft im Hintergrund, damit die HTTP-Flaeche, ueber die der Code kommt,
nicht auf ihn wartet. Eine offene Frage verfaellt nach 15 Minuten.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard
2026-10-02 18:59:37 +02:00
co-authored by Claude Opus 5.5
parent 93395c9e01
commit 4e41fc12d7
9 changed files with 385 additions and 9 deletions
@@ -0,0 +1,71 @@
using ClawdDotNet.App.Services;
using Shouldly;
namespace ClawdDotNet.App.Tests.Services;
/// <summary>
/// #794: The Telegram client login through the WebUI — the question waits for the answer,
/// and an answer without a question goes nowhere.
/// </summary>
public sealed class TelegramLoginBrokerTests
{
[Fact]
public async Task The_code_from_the_web_reaches_the_waiting_login()
{
var broker = new TelegramLoginBroker(configured: true);
var waiting = broker.AskForCodeAsync("code?");
broker.Status.State.ShouldBe(TelegramLoginState.NeedsCode);
broker.Answer(" 12345 ").Ok.ShouldBeTrue();
(await waiting).ShouldBe("12345");
broker.Status.State.ShouldBe(TelegramLoginState.Connecting);
}
[Fact]
public void An_answer_without_a_question_is_refused()
{
var broker = new TelegramLoginBroker(configured: true);
broker.Answer("12345").Ok.ShouldBeFalse();
}
[Fact]
public async Task An_answer_is_used_once()
{
var broker = new TelegramLoginBroker(configured: true);
var waiting = broker.AskForPasswordAsync();
broker.Answer("secret").Ok.ShouldBeTrue();
broker.Answer("again").Ok.ShouldBeFalse();
(await waiting).ShouldBe("secret");
}
[Fact]
public void The_status_never_carries_the_answer()
{
var broker = new TelegramLoginBroker(configured: true);
_ = broker.AskForPasswordAsync();
broker.Answer("hunter2");
broker.Status.Message.ShouldNotContain("hunter2");
}
[Fact]
public async Task A_new_question_cancels_an_unanswered_one()
{
var broker = new TelegramLoginBroker(configured: true);
var first = broker.AskForCodeAsync("code?");
var second = broker.AskForCodeAsync("code again?");
await Should.ThrowAsync<TaskCanceledException>(first);
broker.Answer("777").Ok.ShouldBeTrue();
(await second).ShouldBe("777");
}
[Fact]
public void Without_a_client_the_state_says_so()
=> new TelegramLoginBroker(configured: false).Status.State.ShouldBe(TelegramLoginState.NotConfigured);
}