Rund 2.600 Kommentarblöcke in 310 C#-Dateien übersetzt, Begründungen vollständig erhalten: blockweise gleiche Anzahl wie vorher, kein Block unter 60 % seiner Länge, der Code außerhalb der Kommentare per Tokenizer byte-identisch geprüft. Zitate deutscher Oberflächentexte und Testdaten bleiben deutsch. WebUI: Kommentare in JS/CSS/HTML übersetzt, JSDoc-@param an die in 4b umbenannten Parameter angeglichen. Dabei behoben: - 4b hatte "tag" (HTML-Tag) als deutsches "Tag" gelesen und zu "dayValue" gemacht (makeElement, svg, Tagesübersicht) - zurück auf tag/day. - Aufgaben "InProgress" bekamen die Plakettenart "laufend", für die es nie eine CSS-Klasse gab - jetzt "success" wie laufende Instanzen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
133 lines
4.6 KiB
C#
133 lines
4.6 KiB
C#
using ClawdDotNet.Core.Engine;
|
|
using ClawdDotNet.Core.Staging;
|
|
using ClawdDotNet.Core.Tasks;
|
|
using ClawdDotNet.Web.Contracts;
|
|
using ClawdDotNet.Web.Endpoints;
|
|
using Shouldly;
|
|
|
|
namespace ClawdDotNet.Web.Tests;
|
|
|
|
/// <summary>
|
|
/// Findings from reviewing the web UI in test operation (#572): #591 (field names) and
|
|
/// #536 (direction of the A2A answers).
|
|
/// </summary>
|
|
public sealed class TestbetriebWebTests
|
|
{
|
|
// ─── #591 event stream and transfer types ───
|
|
|
|
[Fact]
|
|
public void Protokollzeilen_im_Ereignisstrom_kommen_in_camelCase()
|
|
{
|
|
var ereignis = EventEndpoints.Format("log", new LogLineDto("Startup", "INF", "ClawdDotNet startet"));
|
|
|
|
ereignis.ShouldStartWith("event: log\n");
|
|
ereignis.ShouldContain("\"module\":\"Startup\"");
|
|
ereignis.ShouldContain("\"level\":\"INF\"");
|
|
ereignis.ShouldContain("\"text\":\"ClawdDotNet startet\"");
|
|
ereignis.ShouldNotContain("\"Text\"", Case.Sensitive);
|
|
}
|
|
|
|
[Fact]
|
|
public void Freigabe_traegt_ihren_Zeitpunkt()
|
|
{
|
|
var angelegt = new DateTime(2026, 9, 14, 10, 18, 53, DateTimeKind.Utc);
|
|
|
|
var dto = new StagedCall
|
|
{
|
|
Id = 1, AgentId = "hausmeister", Tool = "FileRW", Action = "delete",
|
|
ArgumentsJson = "{\"path\":\"betrieb/probe-loeschung.txt\"}", CreatedAt = angelegt
|
|
}.ToDto();
|
|
|
|
dto.CreatedAt.ShouldBe(angelegt);
|
|
dto.Tool.ShouldBe("FileRW");
|
|
dto.Action.ShouldBe("delete");
|
|
}
|
|
|
|
[Fact]
|
|
public void Aufgabe_traegt_ihren_Termin()
|
|
{
|
|
var dto = new TaskItem
|
|
{
|
|
Id = "t-a66932", Title = "Wetter Berlin stuendlich", Assignee = "@new:wetterdienst",
|
|
When = new TaskWhen { Kind = TaskWhenKind.Cron, Value = "5 * * * *", TimeZone = "Europe/Berlin" }
|
|
}.ToDto();
|
|
|
|
dto.When.ShouldNotBeNull();
|
|
dto.When.Kind.ShouldBe("cron");
|
|
dto.When.Value.ShouldBe("5 * * * *");
|
|
dto.When.TimeZone.ShouldBe("Europe/Berlin");
|
|
dto.Assignee.ShouldBe("@new:wetterdienst");
|
|
}
|
|
|
|
[Fact]
|
|
public void Einmalige_Aufgabe_hat_keinen_Termin()
|
|
=> new TaskItem { Id = "t-1", Title = "Einrichtung" }.ToDto().When.ShouldBeNull();
|
|
|
|
// ─── #536 sender and recipient ───
|
|
|
|
private static ChatEntry Anfrage(string vonName, string vonId, string text, int minute)
|
|
=> new("user", $"[Nachricht von Agent \"{vonName}\" ({vonId})]\n\n{text}",
|
|
new DateTime(2026, 9, 14, 12, minute, 0), ChatSource.AgentComm);
|
|
|
|
private static ChatEntry Antwort(string text, int minute)
|
|
=> new("assistant", text, new DateTime(2026, 9, 14, 12, minute, 30), ChatSource.AgentComm);
|
|
|
|
[Fact]
|
|
public void Antwort_geht_vom_Antwortenden_an_den_Fragenden()
|
|
{
|
|
var liste = AgentCommunicationBuilder.Build(
|
|
[
|
|
("redaktion", "Redaktion", (IEnumerable<ChatEntry>)
|
|
[
|
|
Anfrage("Hausmeister", "hausmeister", "Testnachricht", 48),
|
|
Antwort("Empfang bestaetigt", 48)
|
|
])
|
|
]);
|
|
|
|
liste.Count.ShouldBe(2);
|
|
|
|
var anfrage = liste[0];
|
|
anfrage.SourceAgentId.ShouldBe("hausmeister");
|
|
anfrage.TargetAgentId.ShouldBe("redaktion");
|
|
anfrage.Content.ShouldBe("Testnachricht");
|
|
|
|
var antwort = liste[1];
|
|
antwort.SourceAgentId.ShouldBe("redaktion");
|
|
antwort.TargetAgentId.ShouldBe("hausmeister", "vorher stand hier der Antwortende selbst");
|
|
antwort.TargetAgentName.ShouldBe("Hausmeister");
|
|
}
|
|
|
|
[Fact]
|
|
public void Nur_Agentenkommunikation_wird_aufgenommen()
|
|
{
|
|
var liste = AgentCommunicationBuilder.Build(
|
|
[
|
|
("hausmeister", "Hausmeister", (IEnumerable<ChatEntry>)
|
|
[
|
|
new ChatEntry("user", "Hey, wie gehts?", DateTime.Now, ChatSource.WebUi),
|
|
new ChatEntry("assistant", "Moin!", DateTime.Now, ChatSource.WebUi)
|
|
])
|
|
]);
|
|
|
|
liste.ShouldBeEmpty();
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData("[Nachricht von Agent \"Hausmeister\" ohne Klammer]\n\nText")]
|
|
[InlineData("[Nachricht von Agent \"Bo\"b\" (bob)]\n\nText")]
|
|
[InlineData("[Nachricht von Agent \"")]
|
|
public void Absender_lesen_wirft_bei_unerwarteter_Form_nicht(string inhalt)
|
|
=> Should.NotThrow(() => AgentCommunicationBuilder.LeseAbsender(inhalt));
|
|
|
|
[Fact]
|
|
public void Absender_lesen_liefert_Kennung_Name_und_Text()
|
|
{
|
|
var (id, name, text) = AgentCommunicationBuilder.LeseAbsender(
|
|
"[Nachricht von Agent \"Hausmeister\" (hausmeister)]\n\nHallo Redaktion!");
|
|
|
|
id.ShouldBe("hausmeister");
|
|
name.ShouldBe("Hausmeister");
|
|
text.ShouldBe("Hallo Redaktion!");
|
|
}
|
|
}
|