Files
ClawdDotNet/tests/ClawdDotNet.Web.Tests/WebUiOptionsTests.cs
T
Richard 928da7e6af Standardport fuer WebUI auf 7001 geaendert
- InstanceConfig.WebServerPort von 8080 auf 7001 vorbelegt

- Dokumentation und WebUiOptionsTests nachgezogen
2026-09-08 12:37:57 +02:00

123 lines
3.9 KiB
C#

using ClawdDotNet.Core.Config;
using Shouldly;
namespace ClawdDotNet.Web.Tests;
/// <summary>
/// Die Weboberfläche macht aus einer lokalen Anwendung einen Netzwerkdienst, der Agenten
/// mit Datei-, Mail-, FTP- und Datenbankzugriff steuert. Was hier geprüft wird, sind
/// keine Feinheiten der Konfiguration, sondern die Bedingungen, unter denen sie
/// überhaupt hochkommen darf.
/// </summary>
public sealed class WebUiOptionsTests
{
private static InstanceConfig Instanz(
bool enabled = true,
string binding = "loopback",
string token = "ein-hinreichend-langes-token",
int port = 7001)
=> new()
{
WebUiEnabled = enabled,
WebUiBinding = binding,
WebUiToken = token,
WebServerPort = port
};
[Fact]
public void Sie_ist_in_der_Vorbelegung_aus()
{
// Wer einen Netzwerkdienst will, schaltet ihn ein. Nicht andersherum.
new InstanceConfig().WebUiEnabled.ShouldBeFalse();
new InstanceConfig().WebUiBinding.ShouldBe("loopback");
new InstanceConfig().WebServerPort.ShouldBe(7001);
}
[Fact]
public void Abgeschaltet_ist_kein_Fehler()
{
WebUiOptions.TryCreate(Instanz(enabled: false), out var problem).ShouldBeNull();
problem.ShouldBeNull();
}
[Fact]
public void Ohne_Token_startet_sie_nicht_einmal_auf_Loopback()
{
// Auf einer Maschine, auf der Agenten Browser-Werkzeuge bedienen, ist
// „localhost" keine Vertrauensgrenze.
WebUiOptions.TryCreate(Instanz(token: ""), out var problem).ShouldBeNull();
problem.ShouldNotBeNull();
}
[Fact]
public void Alle_Adressen_ohne_Token_werden_abgelehnt_und_nicht_bemaengelt()
{
var options = WebUiOptions.TryCreate(Instanz(binding: "any", token: ""), out var problem);
options.ShouldBeNull();
problem.ShouldNotBeNull();
problem!.ShouldContain("So wird sie nicht gestartet");
}
[Fact]
public void Ein_zu_kurzes_Token_zaehlt_nicht()
{
WebUiOptions.TryCreate(Instanz(token: "kurz"), out var problem).ShouldBeNull();
problem.ShouldNotBeNull();
}
[Fact]
public void Loopback_bindet_an_127_0_0_1()
{
var options = WebUiOptions.TryCreate(Instanz(port: 9001), out _);
options.ShouldNotBeNull();
options!.Url.ShouldBe("http://127.0.0.1:9001");
options.LoopbackOnly.ShouldBeTrue();
}
[Fact]
public void Alles_ausser_any_bleibt_Loopback()
{
// Ein Tippfehler in der Instanzdatei darf die Oberflaeche nicht ins Netz stellen.
WebUiOptions.TryCreate(Instanz(binding: "alle"), out _)!.LoopbackOnly.ShouldBeTrue();
WebUiOptions.TryCreate(Instanz(binding: ""), out _)!.LoopbackOnly.ShouldBeTrue();
}
[Fact]
public void Mit_Token_darf_sie_an_alle_Adressen()
{
var options = WebUiOptions.TryCreate(Instanz(binding: "ANY"), out _);
options.ShouldNotBeNull();
options!.LoopbackOnly.ShouldBeFalse();
options.Url.ShouldStartWith("http://0.0.0.0:");
}
[Theory]
[InlineData(0)]
[InlineData(-1)]
[InlineData(70000)]
public void Ein_unmoeglicher_Port_wird_abgelehnt(int port)
{
WebUiOptions.TryCreate(Instanz(port: port), out var problem).ShouldBeNull();
problem.ShouldNotBeNull();
}
[Fact]
public void Das_Token_steht_geschuetzt_in_der_Instanzdatei()
{
// Ohne den Eintrag in ConfigSecrets staende es im Klartext neben dem
// geschuetzten OpenRouter-Schluessel.
Core.Security.ConfigSecrets.IsSecretKey("webUiToken").ShouldBeTrue();
var config = Instanz(token: "ein-hinreichend-langes-token");
Core.Security.ConfigSecrets.Protect(config);
config.WebUiToken.ShouldNotBe("ein-hinreichend-langes-token");
Core.Security.ConfigSecrets.Unprotect(config);
config.WebUiToken.ShouldBe("ein-hinreichend-langes-token");
}
}